From 00f91b2a00c16b1cb500de9a700c169b683c51da Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 00:11:57 +0100 Subject: [PATCH 01/15] re-order the 'lf em' commands --- client/CMakeLists.txt | 3 +- client/Makefile | 3 +- client/src/cmddata.c | 2 +- client/src/cmdlf.c | 13 +- client/src/cmdlfem.c | 41 ++ client/src/{cmdlfem4x.h => cmdlfem.h} | 13 +- client/src/cmdlfem4x.c | 673 -------------------------- client/src/cmdlfem4x05.c | 447 +++++++++-------- client/src/cmdlfem4x50.c | 27 ++ client/src/cmdlfem4x50.h | 2 + doc/cliparser_todo.txt | 25 +- doc/commands.md | 28 +- 12 files changed, 347 insertions(+), 930 deletions(-) create mode 100644 client/src/cmdlfem.c rename client/src/{cmdlfem4x.h => cmdlfem.h} (54%) delete mode 100644 client/src/cmdlfem4x.c diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 92888a0fa..b630bf5de 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -248,7 +248,8 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/cmdlfawid.c ${PM3_ROOT}/client/src/cmdlfcotag.c ${PM3_ROOT}/client/src/cmdlfdestron.c - ${PM3_ROOT}/client/src/cmdlfem4x.c + ${PM3_ROOT}/client/src/cmdlfem.c + ${PM3_ROOT}/client/src/cmdlfem410x.c ${PM3_ROOT}/client/src/cmdlfem4x05.c ${PM3_ROOT}/client/src/cmdlfem4x50.c ${PM3_ROOT}/client/src/cmdlffdxb.c diff --git a/client/Makefile b/client/Makefile index 2f0899bc8..d577b0d25 100644 --- a/client/Makefile +++ b/client/Makefile @@ -489,7 +489,8 @@ SRCS = aiddesfire.c \ cmdlfawid.c \ cmdlfcotag.c \ cmdlfdestron.c \ - cmdlfem4x.c \ + cmdlfem.c \ + cmdlfem410x.c \ cmdlfem4x05.c \ cmdlfem4x50.c \ cmdlffdxb.c \ diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 3aa7b07fd..d1855aaff 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -23,7 +23,7 @@ #include "comms.h" #include "lfdemod.h" // for demod code #include "loclass/cipherutils.h" // for decimating samples in getsamples -#include "cmdlfem4x.h" // askem410xdecode +#include "cmdlfem410x.h" // askem410xdecode #include "fileutils.h" // searchFile #include "mifare/ndef.h" #include "cliparser.h" diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 7cd9d801e..cbecb8f87 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -12,24 +12,23 @@ // Low frequency commands //----------------------------------------------------------------------------- #include "cmdlf.h" - #include #include #include #include #include - -#include "cmdparser.h" // command_t +#include "cmdparser.h" // command_t #include "comms.h" -#include "commonutil.h" // ARRAYLEN - +#include "commonutil.h" // ARRAYLEN #include "lfdemod.h" // device/client demods of LF signals #include "ui.h" // for show graph controls #include "proxgui.h" +#include "cliparser.h" // args parsing #include "graph.h" // for graph data #include "cmddata.h" // for `lf search` #include "cmdlfawid.h" // for awid menu -#include "cmdlfem4x.h" // for em4x menu +#include "cmdlfem.h" // for em menu +#include "cmdlfem410x.h" // for em4x menu #include "cmdlfem4x05.h" // for em4x05 / 4x69 #include "cmdlfem4x50.h" // for em4x50 #include "cmdlfhid.h" // for hid menu @@ -1530,7 +1529,7 @@ static command_t CommandTable[] = { {"awid", CmdLFAWID, AlwaysAvailable, "{ AWID RFIDs... }"}, {"cotag", CmdLFCOTAG, AlwaysAvailable, "{ COTAG CHIPs... }"}, {"destron", CmdLFDestron, AlwaysAvailable, "{ FDX-A Destron RFIDs... }"}, - {"em", CmdLFEM4X, AlwaysAvailable, "{ EM4X CHIPs & RFIDs... }"}, + {"em", CmdLFEM, AlwaysAvailable, "{ EM CHIPs & RFIDs... }"}, {"fdxb", CmdLFFdxB, AlwaysAvailable, "{ FDX-B RFIDs... }"}, {"gallagher", CmdLFGallagher, AlwaysAvailable, "{ GALLAGHER RFIDs... }"}, {"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"}, diff --git a/client/src/cmdlfem.c b/client/src/cmdlfem.c new file mode 100644 index 000000000..fbc7ac476 --- /dev/null +++ b/client/src/cmdlfem.c @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2020 iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency EM4x commands +//----------------------------------------------------------------------------- + +#include "cmdlfem.h" +#include "cmdlfem410x.h" +#include "cmdlfem4x05.h" +#include "cmdlfem4x50.h" + +#include +#include +#include "cmdparser.h" // command_t +#include "comms.h" // clearCommandBuffer +#include "cmdlf.h" + +static int CmdHelp(const char *Cmd); + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"410x", CmdLFEM410X, AlwaysAvailable, "EM 410x commands..."}, + {"4x05", CmdLFEM4X05, AlwaysAvailable, "EM 4x05 commands..."}, + {"4x50", CmdLFEM4X50, AlwaysAvailable, "EM 4x50 commands..."}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdLFEM(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} diff --git a/client/src/cmdlfem4x.h b/client/src/cmdlfem.h similarity index 54% rename from client/src/cmdlfem4x.h rename to client/src/cmdlfem.h index 34801000e..c4f987b0e 100644 --- a/client/src/cmdlfem4x.h +++ b/client/src/cmdlfem.h @@ -1,11 +1,10 @@ //----------------------------------------------------------------------------- -// Copyright (C) 2010 iZsh -// 2016, 2017 marshmellow, iceman +// Copyright (C) 2020 iceman // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency EM4x commands +// Low frequency EM commands //----------------------------------------------------------------------------- #ifndef CMDLFEM4X_H__ @@ -13,12 +12,6 @@ #include "common.h" -int CmdLFEM4X(const char *Cmd); - -int demodEM410x(bool verbose); -void printEM410x(uint32_t hi, uint64_t id); - -int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo); -int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose); +int CmdLFEM(const char *Cmd); #endif diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem4x.c deleted file mode 100644 index 9c1c7e0a6..000000000 --- a/client/src/cmdlfem4x.c +++ /dev/null @@ -1,673 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2010 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Low frequency EM4x commands -//----------------------------------------------------------------------------- - -#include "cmdlfem4x.h" -#include "cmdlfem4x05.h" -#include "cmdlfem4x50.h" - -#include -#include -#include -#include -#include - -#include "fileutils.h" -#include "cmdparser.h" // command_t -#include "comms.h" -#include "commonutil.h" -#include "common.h" -#include "util_posix.h" -#include "protocols.h" -#include "ui.h" -#include "proxgui.h" -#include "graph.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "lfdemod.h" -#include "generator.h" -#include "cliparser.h" -#include "cmdhw.h" - -static uint64_t g_em410xid = 0; - -static int CmdHelp(const char *Cmd); - -//////////////// 410x commands -static int usage_lf_em410x_demod(void) { - PrintAndLogEx(NORMAL, "Usage: lf em 410x_demod [h] [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " clock - set clock as integer, optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " <0|1> - 0 normal output, 1 for invert output"); - PrintAndLogEx(NORMAL, " maxerror - set maximum allowed errors, default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod") " = demod an EM410x Tag ID from GraphBuffer"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 32") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 32 1") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 1") " = demod an EM410x Tag ID from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 64 1 0") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"); - return PM3_SUCCESS; -} -static int usage_lf_em410x_watch(void) { - PrintAndLogEx(NORMAL, "Enables IOProx compatible reader mode printing details of scanned tags."); - PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 410x_watch"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_watch")); - return PM3_SUCCESS; -} - -static int usage_lf_em410x_clone(void) { - PrintAndLogEx(NORMAL, "Writes EM410x ID to a T55x7 or Q5/T5555 tag"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 410x_clone [h] [clock]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " - ID number"); - PrintAndLogEx(NORMAL, " - 0|1 0 = Q5/T5555, 1 = T55x7"); - PrintAndLogEx(NORMAL, " - 16|32|40|64, optional, set R/F clock rate, defaults to 64"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_clone 0F0368568B 1") " = write ID to t55x7 card"); - return PM3_SUCCESS; -} -static int usage_lf_em410x_ws(void) { - PrintAndLogEx(NORMAL, "Watch 'nd Spoof, activates reader, waits until a EM410x tag gets presented then it starts simulating the found UID"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 410x_spoof [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_spoof")); - return PM3_SUCCESS; -} -static int usage_lf_em410x_sim(void) { - PrintAndLogEx(NORMAL, "Simulating EM410x tag"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 410x_sim [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " uid - uid (10 HEX symbols)"); - PrintAndLogEx(NORMAL, " clock - clock (32|64) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_sim 0F0368568B")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_sim 0F0368568B 32")); - return PM3_SUCCESS; -} -static int usage_lf_em410x_brute(void) { - PrintAndLogEx(NORMAL, "Bruteforcing by emulating EM410x tag"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 410x_brute [h] ids.txt [d 2000] [c clock]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " ids.txt - file with UIDs in HEX format, one per line"); - PrintAndLogEx(NORMAL, " d (2000) - pause delay in milliseconds between UIDs simulation, default 1000 ms (optional)"); - PrintAndLogEx(NORMAL, " c (32) - clock (32|64), default 64 (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt c 32")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt d 3000")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt d 3000 c 32")); - return PM3_SUCCESS; -} - -/* Read the ID of an EM410x tag. - * Format: - * 1111 1111 1 <-- standard non-repeatable header - * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID - * .... - * CCCC <-- each bit here is parity for the 10 bits above in corresponding column - * 0 <-- stop bit, end of tag - */ - -// Construct the graph for emulating an EM410X tag -static void ConstructEM410xEmulGraph(const char *uid, const uint8_t clock) { - - int i, j, binary[4], parity[4]; - uint32_t n; - /* clear our graph */ - ClearGraph(true); - - /* write 16 zero bit sledge */ - for (i = 0; i < 20; i++) - AppendGraph(false, clock, 0); - - /* write 9 start bits */ - for (i = 0; i < 9; i++) - AppendGraph(false, clock, 1); - - /* for each hex char */ - parity[0] = parity[1] = parity[2] = parity[3] = 0; - for (i = 0; i < 10; i++) { - /* read each hex char */ - sscanf(&uid[i], "%1x", &n); - for (j = 3; j >= 0; j--, n /= 2) - binary[j] = n % 2; - - /* append each bit */ - AppendGraph(false, clock, binary[0]); - AppendGraph(false, clock, binary[1]); - AppendGraph(false, clock, binary[2]); - AppendGraph(false, clock, binary[3]); - - /* append parity bit */ - AppendGraph(false, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); - - /* keep track of column parity */ - parity[0] ^= binary[0]; - parity[1] ^= binary[1]; - parity[2] ^= binary[2]; - parity[3] ^= binary[3]; - } - - /* parity columns */ - AppendGraph(false, clock, parity[0]); - AppendGraph(false, clock, parity[1]); - AppendGraph(false, clock, parity[2]); - AppendGraph(false, clock, parity[3]); - - /* stop bit */ - AppendGraph(true, clock, 0); -} - -//by marshmellow -//print 64 bit EM410x ID in multiple formats -void printEM410x(uint32_t hi, uint64_t id) { - - if (!id && !hi) return; - - PrintAndLogEx(SUCCESS, "EM410x%s pattern found", (hi) ? " XL" : ""); - - uint64_t n = 1; - uint64_t id2lo = 0; - uint8_t m, i; - for (m = 5; m > 0; m--) { - for (i = 0; i < 8; i++) { - id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); - } - } - - if (hi) { - //output 88 bit em id - PrintAndLogEx(NORMAL, "\nEM TAG ID : "_YELLOW_("%06X%016" PRIX64), hi, id); - PrintAndLogEx(NORMAL, "Clock rate : "_YELLOW_("RF/%d"), g_DemodClock); - } else { - //output 40 bit em id - PrintAndLogEx(NORMAL, "\nEM TAG ID : "_YELLOW_("%010" PRIX64), id); - PrintAndLogEx(NORMAL, "Clock rate : "_YELLOW_("RF/%d"), g_DemodClock); - PrintAndLogEx(NORMAL, "\nPossible de-scramble patterns\n"); - PrintAndLogEx(NORMAL, "Unique TAG ID : %010" PRIX64, id2lo); - PrintAndLogEx(NORMAL, "HoneyWell IdentKey {"); - PrintAndLogEx(NORMAL, "DEZ 8 : %08" PRIu64, id & 0xFFFFFF); - PrintAndLogEx(NORMAL, "DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF); - PrintAndLogEx(NORMAL, "DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id >> 16LL) & 0xFFFF, (id & 0xFFFF)); - PrintAndLogEx(NORMAL, "DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id >> 32ll), (id & 0xFFFF)); - PrintAndLogEx(NORMAL, "DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF)); - PrintAndLogEx(NORMAL, "DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF)); - PrintAndLogEx(NORMAL, "DEZ 14/IK2 : %014" PRIu64, id); - PrintAndLogEx(NORMAL, "DEZ 15/IK3 : %015" PRIu64, id2lo); - PrintAndLogEx(NORMAL, "DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64, - (id2lo & 0xf000000000) >> 36, - (id2lo & 0x0f00000000) >> 32, - (id2lo & 0x00f0000000) >> 28, - (id2lo & 0x000f000000) >> 24, - (id2lo & 0x0000f00000) >> 20, - (id2lo & 0x00000f0000) >> 16, - (id2lo & 0x000000f000) >> 12, - (id2lo & 0x0000000f00) >> 8, - (id2lo & 0x00000000f0) >> 4, - (id2lo & 0x000000000f) - ); - uint64_t paxton = (((id >> 32) << 24) | (id & 0xffffff)) + 0x143e00; - PrintAndLogEx(NORMAL, "}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id & 0xFFFF), ((id >> 16LL) & 0xFF), (id & 0xFFFFFF)); - PrintAndLogEx(NORMAL, "Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton); - - uint32_t p1id = (id & 0xFFFFFF); - uint8_t arr[32] = {0x00}; - int j = 23; - for (int k = 0 ; k < 24; ++k, --j) { - arr[k] = (p1id >> k) & 1; - } - - uint32_t p1 = 0; - - p1 |= arr[23] << 21; - p1 |= arr[22] << 23; - p1 |= arr[21] << 20; - p1 |= arr[20] << 22; - - p1 |= arr[19] << 18; - p1 |= arr[18] << 16; - p1 |= arr[17] << 19; - p1 |= arr[16] << 17; - - p1 |= arr[15] << 13; - p1 |= arr[14] << 15; - p1 |= arr[13] << 12; - p1 |= arr[12] << 14; - - p1 |= arr[11] << 6; - p1 |= arr[10] << 2; - p1 |= arr[9] << 7; - p1 |= arr[8] << 1; - - p1 |= arr[7] << 0; - p1 |= arr[6] << 8; - p1 |= arr[5] << 11; - p1 |= arr[4] << 3; - - p1 |= arr[3] << 10; - p1 |= arr[2] << 4; - p1 |= arr[1] << 5; - p1 |= arr[0] << 9; - PrintAndLogEx(NORMAL, "Pattern 1 : %d [0x%X]", p1, p1); - - uint16_t sebury1 = id & 0xFFFF; - uint8_t sebury2 = (id >> 16) & 0x7F; - uint32_t sebury3 = id & 0x7FFFFF; - PrintAndLogEx(NORMAL, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); - } -} -/* Read the ID of an EM410x tag. - * Format: - * 1111 1111 1 <-- standard non-repeatable header - * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID - * .... - * CCCC <-- each bit here is parity for the 10 bits above in corresponding column - * 0 <-- stop bit, end of tag - */ -int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) { - size_t idx = 0; - uint8_t bits[512] = {0}; - size_t size = sizeof(bits); - if (!getDemodBuff(bits, &size)) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod"); - return PM3_ESOFT; - } - - int ans = Em410xDecode(bits, &size, &idx, hi, lo); - if (ans < 0) { - - if (ans == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod"); - else if (ans == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found"); - else if (ans == -5) - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size); - else if (ans == -6) - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x parity failed"); - - return PM3_ESOFT; - } - if (!lo && !hi) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x decoded to all zeros"); - return PM3_ESOFT; - } - - //set GraphBuffer for clone or sim command - setDemodBuff(DemodBuffer, (size == 40) ? 64 : 128, idx + 1); - setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock)); - - PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing Demod Buffer:", idx, size); - if (g_debugMode) { - printDemodBuff(0, false, false, true); - } - - if (verbose) - printEM410x(*hi, *lo); - - return PM3_SUCCESS; -} - -int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) { - bool st = true; - - // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again - if (isGraphBitstream()) { - convertGraphFromBitstream(); - } - if (ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, false, false, 1, &st) != PM3_SUCCESS) - return PM3_ESOFT; - return AskEm410xDecode(verbose, hi, lo); -} - -// this read loops on device side. -// uses the demod in lfops.c -static int CmdEM410xWatch(const char *Cmd) { - uint8_t c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_lf_em410x_watch(); - - PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on antenna"); - PrintAndLogEx(INFO, "Press pm3-button to stop reading cards"); - clearCommandBuffer(); - SendCommandNG(CMD_LF_EM410X_WATCH, NULL, 0); - PacketResponseNG resp; - WaitForResponse(CMD_LF_EM410X_WATCH, &resp); - PrintAndLogEx(INFO, "Done"); - return resp.status; -} - -//by marshmellow -//takes 3 arguments - clock, invert and maxErr as integers -//attempts to demodulate ask while decoding manchester -//prints binary found and saves in graphbuffer for further commands -int demodEM410x(bool verbose) { - (void) verbose; // unused so far - uint32_t hi = 0; - uint64_t lo = 0; - return AskEm410xDemod(0, 0, 100, 0, false, &hi, &lo, true); -} - -static int CmdEM410xDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); - - uint32_t hi = 0; - uint64_t lo = 0; - int clk = 0; - int invert = 0; - int maxErr = 100; - size_t maxLen = 0; - char amp = tolower(param_getchar(Cmd, 0)); - sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); - bool amplify = amp == 'a'; - if (AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true) != PM3_SUCCESS) - return PM3_ESOFT; - - g_em410xid = lo; - return PM3_SUCCESS; -} - -// this read is the "normal" read, which download lf signal and tries to demod here. -static int CmdEM410xRead(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); - - uint32_t hi = 0; - uint64_t lo = 0; - int clk = 0; - int invert = 0; - int maxErr = 100; - size_t maxLen = 0; - char amp = tolower(param_getchar(Cmd, 0)); - sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); - bool amplify = amp == 'a'; - lf_read(false, 12288); - return AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true); -} - -// emulate an EM410X tag -static int CmdEM410xSim(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_lf_em410x_sim(); - - uint8_t uid[5] = {0x00}; - - /* clock is 64 in EM410x tags */ - uint8_t clk = 64; - - if (param_gethex(Cmd, 0, uid, 10)) { - PrintAndLogEx(FAILED, "UID must include 10 HEX symbols"); - return PM3_EINVARG; - } - - param_getdec(Cmd, 1, &clk); - - PrintAndLogEx(SUCCESS, "Starting simulating UID "_YELLOW_("%02X%02X%02X%02X%02X")" clock: "_YELLOW_("%d"), uid[0], uid[1], uid[2], uid[3], uid[4], clk); - PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); - - ConstructEM410xEmulGraph(Cmd, clk); - - CmdLFSim("0"); //240 start_gap. - return PM3_SUCCESS; -} - -static int CmdEM410xBrute(const char *Cmd) { - char filename[FILE_PATH_SIZE] = {0}; - FILE *f = NULL; - char buf[11]; - uint32_t uidcnt = 0; - uint8_t stUidBlock = 20; - uint8_t *uidBlock = NULL, *p = NULL; - uint8_t uid[5] = {0x00}; - /* clock is 64 in EM410x tags */ - uint8_t clock1 = 64; - /* default pause time: 1 second */ - uint32_t delay = 1000; - - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_lf_em410x_brute(); - - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 'd') { - delay = param_get32ex(Cmd, 2, 1000, 10); - param_getdec(Cmd, 4, &clock1); - } else if (cmdp == 'c') { - param_getdec(Cmd, 2, &clock1); - delay = param_get32ex(Cmd, 4, 1000, 10); - } - - int filelen = param_getstr(Cmd, 0, filename, FILE_PATH_SIZE); - if (filelen == 0) { - PrintAndLogEx(ERR, "Error: Please specify a filename"); - return PM3_EINVARG; - } - - if ((f = fopen(filename, "r")) == NULL) { - PrintAndLogEx(ERR, "Error: Could not open UIDs file ["_YELLOW_("%s")"]", filename); - return PM3_EFILE; - } - - uidBlock = calloc(stUidBlock, 5); - if (uidBlock == NULL) { - fclose(f); - return PM3_ESOFT; - } - - while (fgets(buf, sizeof(buf), f)) { - if (strlen(buf) < 10 || buf[9] == '\n') continue; - while (fgetc(f) != '\n' && !feof(f)); //goto next line - - //The line start with # is comment, skip - if (buf[0] == '#') continue; - - if (param_gethex(buf, 0, uid, 10)) { - PrintAndLogEx(FAILED, "UIDs must include 10 HEX symbols"); - free(uidBlock); - fclose(f); - return PM3_ESOFT; - } - - buf[10] = 0; - - if (stUidBlock - uidcnt < 2) { - p = realloc(uidBlock, 5 * (stUidBlock += 10)); - if (!p) { - PrintAndLogEx(WARNING, "Cannot allocate memory for UIDs"); - free(uidBlock); - fclose(f); - return PM3_ESOFT; - } - uidBlock = p; - } - memset(uidBlock + 5 * uidcnt, 0, 5); - num_to_bytes(strtoll(buf, NULL, 16), 5, uidBlock + 5 * uidcnt); - uidcnt++; - memset(buf, 0, sizeof(buf)); - } - - fclose(f); - - if (uidcnt == 0) { - PrintAndLogEx(FAILED, "No UIDs found in file"); - free(uidBlock); - return PM3_ESOFT; - } - - PrintAndLogEx(SUCCESS, "Loaded "_YELLOW_("%d")" UIDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt, filename, delay); - - // loop - for (uint32_t c = 0; c < uidcnt; ++c) { - char testuid[11]; - testuid[10] = 0; - - if (kbd_enter_pressed()) { - PrintAndLogEx(WARNING, "\nAborted via keyboard!\n"); - free(uidBlock); - return PM3_EOPABORTED; - } - - sprintf(testuid, "%010" PRIX64, bytes_to_num(uidBlock + 5 * c, 5)); - PrintAndLogEx(NORMAL, "Bruteforce %d / %d: simulating UID %s, clock %d", c + 1, uidcnt, testuid, clock1); - - ConstructEM410xEmulGraph(testuid, clock1); - - CmdLFSim("0"); //240 start_gap. - - msleep(delay); - } - - free(uidBlock); - return PM3_SUCCESS; -} - -//currently only supports manchester modulations -static int CmdEM410xWatchnSpoof(const char *Cmd) { - - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_lf_em410x_ws(); - - // loops if the captured ID was in XL-format. - CmdEM410xWatch(Cmd); - PrintAndLogEx(SUCCESS, "# Replaying captured ID: "_YELLOW_("%010" PRIx64), g_em410xid); - CmdLFaskSim(""); - return PM3_SUCCESS; -} - -static int CmdEM410xClone(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 0x00 || cmdp == 'h') return usage_lf_em410x_clone(); - - uint64_t id = param_get64ex(Cmd, 0, -1, 16); - uint8_t card = param_get8ex(Cmd, 1, 0xFF, 10); - uint8_t clock1 = param_get8ex(Cmd, 2, 0, 10); - - // Check ID - if (id == 0xFFFFFFFFFFFFFFFF) { - PrintAndLogEx(ERR, "error, ID is required\n"); - usage_lf_em410x_clone(); - return PM3_EINVARG; - } - if (id >= 0x10000000000) { - PrintAndLogEx(ERR, "error, given EM410x ID is longer than 40 bits\n"); - usage_lf_em410x_clone(); - return PM3_EINVARG; - } - - // Check Card - if (card > 1) { - PrintAndLogEx(FAILED, "error, bad card type selected\n"); - usage_lf_em410x_clone(); - return PM3_EINVARG; - } - - // Check Clock - if (clock1 == 0) - clock1 = 64; - - // Allowed clock rates: 16, 32, 40 and 64 - if ((clock1 != 16) && (clock1 != 32) && (clock1 != 64) && (clock1 != 40)) { - PrintAndLogEx(FAILED, "error, clock rate" _RED_("%d")" not valid", clock1); - PrintAndLogEx(INFO, "supported clock rates: " _YELLOW_("16, 32, 40, 60") "\n"); - usage_lf_em410x_clone(); - return PM3_EINVARG; - } - - PrintAndLogEx(SUCCESS, "Writing " _YELLOW_("%s") " tag with UID 0x%010" PRIx64 " (clock rate: %d)", (card == 1) ? "T55x7" : "Q5/T5555", id, clock1); - // NOTE: We really should pass the clock in as a separate argument, but to - // provide for backwards-compatibility for older firmware, and to avoid - // having to add another argument to CMD_LF_EM410X_WRITE, we just store - // the clock rate in bits 8-15 of the card value - - struct { - uint8_t card; - uint8_t clock; - uint32_t high; - uint32_t low; - } PACKED params; - - params.card = card; - params.clock = clock1; - params.high = (uint32_t)(id >> 32); - params.low = (uint32_t)id; - - clearCommandBuffer(); - SendCommandNG(CMD_LF_EM410X_WRITE, (uint8_t *)¶ms, sizeof(params)); - - PacketResponseNG resp; - WaitForResponse(CMD_LF_EM410X_WRITE, &resp); - switch (resp.status) { - case PM3_SUCCESS: { - PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x_read`") " to verify"); - break; - } - default: { - PrintAndLogEx(WARNING, "Something went wrong"); - break; - } - } - return resp.status; -} - -static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 410x") " -----------------------"}, - //{"410x_demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"}, - {"410x_demod", CmdEM410xDemod, AlwaysAvailable, "demodulate a EM410x tag from the GraphBuffer"}, - {"410x_read", CmdEM410xRead, IfPm3Lf, "attempt to read and extract tag data"}, - {"410x_sim", CmdEM410xSim, IfPm3Lf, "simulate EM410x tag"}, - {"410x_brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"}, - {"410x_watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, - {"410x_spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, - {"410x_clone", CmdEM410xClone, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"}, - {"----------", CmdHelp, AlwaysAvailable, "-------------------- " _CYAN_("EM 4x05 / 4x69") " -------------------"}, - {"4x05_chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords from dictionary"}, - {"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"}, - {"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"}, - {"4x05_wipe", CmdEM4x05Wipe, IfPm3Lf, "wipe EM4x05/EM4x69 tag"}, - {"4x05_info", CmdEM4x05Info, IfPm3Lf, "tag information EM4x05/EM4x69"}, - {"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"}, - {"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"}, - {"4x05_unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"}, - {"4x05_sniff", CmdEM4x05Sniff, AlwaysAvailable, "Attempt to recover em4x05 commands from sample buffer"}, - {"4x05_brute", CmdEM4x05Brute, IfPm3Lf, "Bruteforce password"}, - {"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"}, - {"4x50_dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"}, - {"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"}, - {"4x50_write", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"}, - {"4x50_write_password", CmdEM4x50WritePassword, IfPm3EM4x50, "change password of EM4x50 tag"}, - {"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, - {"4x50_wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe data from EM4x50"}, - {NULL, NULL, NULL, NULL} -}; - -static int CmdHelp(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - CmdsHelp(CommandTable); - return PM3_SUCCESS; -} - -int CmdLFEM4X(const char *Cmd) { - clearCommandBuffer(); - return CmdsParse(CommandTable, Cmd); -} diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 3b260ed2e..0f968d23d 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -38,59 +38,7 @@ #define EM_PREAMBLE_LEN 8 -static int usage_lf_em4x05_wipe(void) { - PrintAndLogEx(NORMAL, "Wipe EM4x05/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x05_wipe [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " c - chip type : 0 em4205"); - PrintAndLogEx(NORMAL, " 1 em4305 (default)"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x05_wipe"); - PrintAndLogEx(NORMAL, " lf em 4x05_wipe 11223344"); - return PM3_SUCCESS; -} -static int usage_lf_em4x05_read(void) { - PrintAndLogEx(NORMAL, "Read EM4x05/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x05_read [h]
"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " address - memory address to read. (0-15)"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x05_read 1"); - PrintAndLogEx(NORMAL, " lf em 4x05_read 1 11223344"); - return PM3_SUCCESS; -} -static int usage_lf_em4x05_write(void) { - PrintAndLogEx(NORMAL, "Write EM4x05/4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x05_write [h]
"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " address - memory address to write to. (0-13, 99 for Protection Words)"); - PrintAndLogEx(NORMAL, " data - data to write (hex)"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x05_write 1 deadc0de"); - PrintAndLogEx(NORMAL, " lf em 4x05_write 1 deadc0de 11223344"); - return PM3_SUCCESS; -} -static int usage_lf_em4x05_info(void) { - PrintAndLogEx(NORMAL, "Tag information EM4205/4305/4469//4569 tags. Tag must be on antenna."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x05_info [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x05_info"); - PrintAndLogEx(NORMAL, " lf em 4x05_info deadc0de"); - return PM3_SUCCESS; -} +static int CmdHelp(const char *Cmd); // 1 = EM4x69 // 2 = EM4x05 @@ -140,7 +88,6 @@ static bool em4x05_col_parity_test(uint8_t *bs, size_t size, uint8_t rows, uint8 return true; } - // download samples from device and copy to Graphbuffer static bool em4x05_download_samples(void) { @@ -387,6 +334,7 @@ static bool em4x05_verify_write(uint8_t addr, uint32_t pwd, bool use_pwd, uint32 uint32_t r = 0; int res = em4x05_read_word_ext(addr, pwd, use_pwd, &r); if (res == PM3_SUCCESS) { + PrintAndLogEx(INFO, "%08x == %08x", r, data); return (r == data); } return false; @@ -506,7 +454,40 @@ int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t dat return PM3_SUCCESS; } +static int em4x05_protect(uint32_t pwd, bool use_pwd, uint32_t data) { + struct { + uint32_t password; + uint32_t data; + uint8_t usepwd; + } PACKED payload; + + payload.password = pwd; + payload.data = data; + payload.usepwd = use_pwd; + + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000)) { + PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); + return PM3_ETIMEOUT; + } + return PM3_SUCCESS; +} + int CmdEM4x05Demod(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x05 demod", + "Try to find EM 4x05 preamble, if found decode / descramble data", + "lf em 4x05 demod" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); uint32_t dummy = 0; return em4x05_demod_resp(&dummy, false); } @@ -514,11 +495,11 @@ int CmdEM4x05Demod(const char *Cmd) { int CmdEM4x05Dump(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em dump", + CLIParserInit(&ctx, "lf em 4x05 dump", "Dump EM4x05/EM4x69. Tag must be on antenna.", - "lf em dump\n" - "lf em dump -p 11223344\n" - "lf em dump -f myfile -p 11223344" + "lf em 4x05 dump\n" + "lf em 4x05 dump -p 11223344\n" + "lf em 4x05 dump -f myfile -p 11223344" ); void *argtable[] = { @@ -734,29 +715,43 @@ int CmdEM4x05Dump(const char *Cmd) { } int CmdEM4x05Read(const char *Cmd) { - uint8_t addr; - uint32_t pwd; - bool usePwd = false; - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_em4x05_read(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x05 read", + "Read EM4x05/EM4x69. Tag must be on antenna.", + "lf em 4x05 read -a 1\n" + "lf em 4x05 read --addr 1 --pwd 11223344" + ); - addr = param_get8ex(Cmd, 0, 50, 10); - pwd = param_get32ex(Cmd, 1, 0xFFFFFFFF, 16); + void *argtable[] = { + arg_param_begin, + arg_int1("a", "addr", "", "memory address to read. (0-15)"), + arg_str0("p", "pwd", "", "optional - password, 4 bytes hex"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50); + uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 2, 0xFFFFFFFFFFFFFFFF); + CLIParserFree(ctx); + + uint32_t pwd = 0; + bool use_pwd = false; if (addr > 15) { - PrintAndLogEx(WARNING, "Address must be between 0 and 15"); - return PM3_ESOFT; + PrintAndLogEx(ERR, "Address must be between 0 and 15"); + return PM3_EINVARG; } - if (pwd == 0xFFFFFFFF) { + + if (inputpwd == 0xFFFFFFFFFFFFFFFF) { PrintAndLogEx(INFO, "Reading address %02u", addr); } else { - usePwd = true; + pwd = (inputpwd & 0xFFFFFFFF); + use_pwd = true; PrintAndLogEx(INFO, "Reading address %02u using password %08X", addr, pwd); } uint32_t word = 0; - int status = em4x05_read_word_ext(addr, pwd, usePwd, &word); + int status = em4x05_read_word_ext(addr, pwd, use_pwd, &word); if (status == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Address %02d | %08X - %s", addr, word, (addr > 13) ? "Lock" : ""); else if (status == PM3_EFAILED) @@ -767,55 +762,61 @@ int CmdEM4x05Read(const char *Cmd) { } int CmdEM4x05Write(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_em4x05_write(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x05 write", + "Write EM4x05/EM4x69. Tag must be on antenna.", + "lf em 4x05 write -a 1 -d deadc0de\n" + "lf em 4x05 write --addr 1 --pwd 11223344 --data deadc0de\n" + "lf em 4x05 write --po --pwd 11223344 --data deadc0de\n" + ); - bool usePwd = false; - uint8_t addr; - uint32_t data, pwd; - - addr = param_get8ex(Cmd, 0, 50, 10); - data = param_get32ex(Cmd, 1, 0, 16); - pwd = param_get32ex(Cmd, 2, 0xFFFFFFFF, 16); - bool protectOperation = addr == 99; // will do better with cliparser... - - if ((addr > 13) && (!protectOperation)) { + void *argtable[] = { + arg_param_begin, + arg_int0("a", "addr", "", "memory address to write to. (0-13)"), + arg_str1("d", "data", "", "data to write, 4 bytes hex"), + arg_str0("p", "pwd", "", "optional - password, 4 bytes hex"), + arg_lit0(NULL, "po", "protect operation"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50); + uint32_t data = arg_get_u32(ctx, 2); + uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 3, 0xFFFFFFFFFFFFFFFF); + bool protect_operation = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + if ((addr > 13) && (protect_operation == false)) { PrintAndLogEx(WARNING, "Address must be between 0 and 13"); return PM3_EINVARG; } + + bool use_pwd = false; + uint32_t pwd = ( inputpwd != 0xFFFFFFFFFFFFFFFF) ? (inputpwd & 0xFFFFFFFF) : 0; if (pwd == 0xFFFFFFFF) { - if (protectOperation) + if (protect_operation) PrintAndLogEx(INFO, "Writing protection words data %08X", data); else PrintAndLogEx(INFO, "Writing address %d data %08X", addr, data); } else { - usePwd = true; - if (protectOperation) + use_pwd = true; + if (protect_operation) PrintAndLogEx(INFO, "Writing protection words data %08X using password %08X", data, pwd); else PrintAndLogEx(INFO, "Writing address %d data %08X using password %08X", addr, data, pwd); } - if (protectOperation) { // set Protect Words - struct { - uint32_t password; - uint32_t data; - uint8_t usepwd; - } PACKED payload; - - payload.password = pwd; - payload.data = data; - payload.usepwd = usePwd; - - clearCommandBuffer(); - SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload)); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; + int res = PM3_SUCCESS; + // set Protect Words + if (protect_operation) { + res = em4x05_protect(pwd, use_pwd, data); + if ( res != PM3_SUCCESS) { + return res; } } else { - em4x05_write_word_ext(addr, pwd, usePwd, data); + res = em4x05_write_word_ext(addr, pwd, use_pwd, data); + if ( res != PM3_SUCCESS) { + return res; + } } if (em4x05_download_samples() == false) @@ -826,86 +827,111 @@ int CmdEM4x05Write(const char *Cmd) { if (status == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Data written and verified"); else if (status == PM3_EFAILED) - PrintAndLogEx(ERR, "Tag denied %s operation", protectOperation ? "Protect" : "Write"); + PrintAndLogEx(ERR, "Tag denied %s operation", protect_operation ? "Protect" : "Write"); else PrintAndLogEx(DEBUG, "No answer from tag"); - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05_read`") " to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05 read`") " to verify"); return status; } int CmdEM4x05Wipe(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x05 wipe", + "Wipe EM4x05/EM4x69. Tag must be on antenna.", + "lf em 4x05 wipe --4305 -p 11223344 -> wipe EM 4305 w pwd\n" + "lf em 4x05 wipe --4205 -> wipe EM 4205\n" + "lf em 4x05 wipe --4369 -> wipe EM 4369" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "4205", "target chip type EM 4205"), + arg_lit0(NULL, "4305", "target chip type EM 4305 (default)"), + arg_lit0(NULL, "4369", "target chip type EM 4369"), + arg_lit0(NULL, "4369", "target chip type EM 4469"), + arg_str0("p", "pwd", "", "optional - password, 4 bytes hex"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool target_4205 = arg_get_lit(ctx, 1); + bool target_4305 = arg_get_lit(ctx, 2); + bool target_4369 = arg_get_lit(ctx, 3); + bool target_4469 = arg_get_lit(ctx, 4); + uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 5, 0xFFFFFFFFFFFFFFFF); + CLIParserFree(ctx); + + uint8_t foo = target_4205 + target_4305 + target_4369 + target_4469; + + if (foo > 1) { + PrintAndLogEx(ERR, "Can't target multiple chip types at the same time"); + return PM3_EINVARG; + } + uint8_t addr = 0; + uint32_t chip_info = 0x00040072; // Chip info/User Block normal 4305 Chip Type + uint32_t chip_UID = 0x614739AE; // UID normally readonly, but just in case + uint32_t block_data = 0x00000000; // UserBlock/Password (set to 0x00000000 for a wiped card1 + uint32_t config = 0x0001805F; // Default config (no password) + + if (target_4205) { + chip_info = 0x00040070; + } + if (target_4369) { + chip_info = 0x00020078; // found on HID Prox + } + if (target_4469) { +// chip_info = 0x00020078; // need to get a normal 4469 chip info block + } + + bool use_pwd = false; uint32_t pwd = 0; - uint8_t cmdp = 0; - uint8_t chipType = 1; // em4305 - uint32_t chipInfo = 0x00040072; // Chip info/User Block normal 4305 Chip Type - uint32_t chipUID = 0x614739AE; // UID normally readonly, but just in case - uint32_t blockData = 0x00000000; // UserBlock/Password (set to 0x00000000 for a wiped card1 - uint32_t config = 0x0001805F; // Default config (no password) - int success = PM3_SUCCESS; - char cmdStr [100]; - char optchk[10]; - - while (param_getchar(Cmd, cmdp) != 0x00) { - // check if cmd is a 1 byte option - param_getstr(Cmd, cmdp, optchk, sizeof(optchk)); - if (strlen(optchk) == 1) { // Have a single character so option not part of password - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'c': // chip type - if (param_getchar(Cmd, cmdp) != 0x00) - chipType = param_get8ex(Cmd, cmdp + 1, 0, 10); - cmdp += 2; - break; - case 'h': // return usage_lf_em4x05_wipe(); - default : // Unknown or 'h' send help - return usage_lf_em4x05_wipe(); - break; - }; - } else { // Not a single character so assume password - pwd = param_get32ex(Cmd, cmdp, 1, 16); - cmdp++; - } + if ( inputpwd != 0xFFFFFFFFFFFFFFFF) { + pwd = (inputpwd & 0xFFFFFFFF); + use_pwd = true; } - - switch (chipType) { - case 0 : // em4205 - chipInfo = 0x00040070; - config = 0x0001805F; - break; - case 1 : // em4305 - chipInfo = 0x00040072; - config = 0x0001805F; - break; - default : // Type 0/Default : EM4305 - chipInfo = 0x00040072; - config = 0x0001805F; - } - // block 0 : User Data or Chip Info - sprintf(cmdStr, "%d %08X %08X", 0, chipInfo, pwd); - CmdEM4x05Write(cmdStr); + int res = em4x05_write_word_ext(0, pwd, use_pwd, chip_info); + if ( res != PM3_SUCCESS) { + return res; + } + // block 1 : UID - this should be read only for EM4205 and EM4305 not sure about others - sprintf(cmdStr, "%d %08X %08X", 1, chipUID, pwd); - CmdEM4x05Write(cmdStr); + res = em4x05_write_word_ext(1, pwd, use_pwd, chip_UID); + if ( res != PM3_SUCCESS) { + PrintAndLogEx(INFO, "UID block write failed"); + } + // block 2 : password - sprintf(cmdStr, "%d %08X %08X", 2, blockData, pwd); - CmdEM4x05Write(cmdStr); - pwd = blockData; // Password should now have changed, so use new password + res = em4x05_write_word_ext(2, pwd, use_pwd, block_data); + if ( res != PM3_SUCCESS) { + return res; + } + + // Password should now have changed, so use new password + pwd = block_data; // block 3 : user data - sprintf(cmdStr, "%d %08X %08X", 3, blockData, pwd); - CmdEM4x05Write(cmdStr); + res = em4x05_write_word_ext(3, pwd, use_pwd, block_data); + if ( res != PM3_SUCCESS) { + return res; + } + // block 4 : config - sprintf(cmdStr, "%d %08X %08X", 4, config, pwd); - CmdEM4x05Write(cmdStr); + res = em4x05_write_word_ext(4, pwd, use_pwd, config); + if ( res != PM3_SUCCESS) { + return res; + } // Remainder of user/data blocks for (addr = 5; addr < 14; addr++) {// Clear user data blocks - sprintf(cmdStr, "%d %08X %08X", addr, blockData, pwd); - CmdEM4x05Write(cmdStr); + res = em4x05_write_word_ext(addr, pwd, use_pwd, block_data); + if ( res != PM3_SUCCESS) { + return res; + } } - - return success; + return PM3_SUCCESS; } static const char *printEM4x05_known(uint32_t word) { @@ -1174,24 +1200,37 @@ static void printEM4x05ProtectionBits(uint32_t word, uint8_t addr) { } } - //quick test for EM4x05/EM4x69 tag bool em4x05_isblock0(uint32_t *word) { return (em4x05_read_word_ext(0, 0, false, word) == PM3_SUCCESS); } int CmdEM4x05Info(const char *Cmd) { - uint32_t pwd; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x05 info", + "Tag information EM4205/4305/4469//4569 tags. Tag must be on antenna.", + "lf em 4x05 info\n" + "lf em 4x05 info -p 11223344" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("p", "pwd", "", "optional - password, 4 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 1, 0xFFFFFFFFFFFFFFFF); + CLIParserFree(ctx); + + bool use_pwd = false; + uint32_t pwd = 0; + if (inputpwd != 0xFFFFFFFFFFFFFFFF) { + pwd = inputpwd & 0xFFFFFFFF; + use_pwd = true; + } + uint32_t word = 0, block0 = 0, serial = 0; - bool usePwd = false; - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x05_info(); - - // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) - pwd = param_get32ex(Cmd, 0, 0xFFFFFFFF, 16); - - if (pwd != 0xFFFFFFFF) - usePwd = true; // read word 0 (chip info) // block 0 can be read even without a password. @@ -1209,7 +1248,7 @@ int CmdEM4x05Info(const char *Cmd) { // read word 4 (config block) // needs password if one is set - if (em4x05_read_word_ext(EM_CONFIG_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS) { + if (em4x05_read_word_ext(EM_CONFIG_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) { PrintAndLogEx(DEBUG, "(CmdEM4x05Info) failed to read CONFIG BLOCK"); return PM3_ESOFT; } @@ -1221,7 +1260,7 @@ int CmdEM4x05Info(const char *Cmd) { if (card_type == EM_4205 || card_type == EM_4305) { // read word 14 and 15 to see which is being used for the protection bits - if (em4x05_read_word_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS) { + if (em4x05_read_word_ext(EM4305_PROT1_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) { return PM3_ESOFT; } @@ -1229,7 +1268,7 @@ int CmdEM4x05Info(const char *Cmd) { printEM4x05ProtectionBits(word, EM4305_PROT1_BLOCK); return PM3_SUCCESS; } else { // if status bit says this is not the used protection word - if (em4x05_read_word_ext(EM4305_PROT2_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS) + if (em4x05_read_word_ext(EM4305_PROT2_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) return PM3_ESOFT; if (word & 0x8000) { printEM4x05ProtectionBits(word, EM4305_PROT2_BLOCK); @@ -1238,7 +1277,7 @@ int CmdEM4x05Info(const char *Cmd) { } } else if (card_type == EM_4369 || card_type == EM_4469) { // read word 3 to see which is being used for the protection bits - if (em4x05_read_word_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS) { + if (em4x05_read_word_ext(EM4469_PROT_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) { return PM3_ESOFT; } printEM4x05ProtectionBits(word, EM4469_PROT_BLOCK); @@ -1259,11 +1298,11 @@ static bool is_cancelled(void) { int CmdEM4x05Chk(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x05_chk", + CLIParserInit(&ctx, "lf em 4x05 chk", "This command uses a dictionary attack against EM4205/4305/4469/4569", - "lf em 4x05_chk\n" - "lf em 4x05_chk -e 000022B8 -> remember to use 0x for hex\n" - "lf em 4x05_chk -f t55xx_default_pwds -> use T55xx default dictionary" + "lf em 4x05 chk\n" + "lf em 4x05 chk -e 000022B8 -> remember to use 0x for hex\n" + "lf em 4x05 chk -f t55xx_default_pwds -> use T55xx default dictionary" ); void *argtable[] = { @@ -1360,12 +1399,12 @@ int CmdEM4x05Chk(const char *Cmd) { int CmdEM4x05Brute(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x05_brute", + CLIParserInit(&ctx, "lf em 4x05 brute", "This command tries to bruteforce the password of a EM4205/4305/4469/4569\n", "Note: if you get many false positives, change position on the antenna" - "lf em 4x05_brute\n" - "lf em 4x05_brute -n 1 -> stop after first candidate found\n" - "lf em 4x05_brute -s 000022B8 -> remember to use 0x for hex" + "lf em 4x05 brute\n" + "lf em 4x05 brute -n 1 -> stop after first candidate found\n" + "lf em 4x05 brute -s 000022B8 -> remember to use 0x for hex" ); void *argtable[] = { @@ -1464,11 +1503,11 @@ static void unlock_add_item(em4x05_unlock_item_t *array, uint8_t len, uint32_t v int CmdEM4x05Unlock(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x05_unlock", + CLIParserInit(&ctx, "lf em 4x05 unlock", "execute tear off against EM4205/4305/4469/4569", - "lf em 4x05_unlock\n" - "lf em 4x05_unlock -s 4100 -e 4100 -> lock on and autotune at 4100us\n" - "lf em 4x05_unlock -n 10 -s 3000 -e 4400 -> scan delays 3000us -> 4400us" + "lf em 4x05 unlock\n" + "lf em 4x05 unlock -s 4100 -e 4100 -> lock on and autotune at 4100us\n" + "lf em 4x05 unlock -n 10 -s 3000 -e 4400 -> scan delays 3000us -> 4400us" ); void *argtable[] = { @@ -2082,3 +2121,29 @@ int CmdEM4x05Sniff(const char *Cmd) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"brute", CmdEM4x05Brute, IfPm3Lf, "Bruteforce password"}, + {"chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords from dictionary"}, + {"demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"}, + {"dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"}, + {"info", CmdEM4x05Info, IfPm3Lf, "tag information EM4x05/EM4x69"}, + {"read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"}, + {"sniff", CmdEM4x05Sniff, AlwaysAvailable, "Attempt to recover em4x05 commands from sample buffer"}, + {"unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"}, + {"wipe", CmdEM4x05Wipe, IfPm3Lf, "wipe EM4x05/EM4x69 tag"}, + {"write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdLFEM4X05(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} \ No newline at end of file diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 2f768c62b..be0b17bb1 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -1,6 +1,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 2020 tharexde // +// modified iceman, 2020 +// // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -10,11 +12,14 @@ #include "cmdlfem4x50.h" #include +#include "cmdparser.h" // command_t #include "fileutils.h" #include "comms.h" #include "commonutil.h" #include "em4x50.h" +static int CmdHelp(const char *Cmd); + static int usage_lf_em4x50_info(void) { PrintAndLogEx(NORMAL, "Read all information of EM4x50. Tag must be on antenna."); PrintAndLogEx(NORMAL, ""); @@ -749,3 +754,25 @@ int CmdEM4x50Wipe(const char *Cmd) { return PM3_SUCCESS; } + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"}, + {"info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"}, + {"write", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"}, + {"write_password", CmdEM4x50WritePassword, IfPm3EM4x50, "change password of EM4x50 tag"}, + {"read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, + {"wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe data from EM4x50"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdLFEM4X50(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} diff --git a/client/src/cmdlfem4x50.h b/client/src/cmdlfem4x50.h index 01417aa1e..36e87ce70 100644 --- a/client/src/cmdlfem4x50.h +++ b/client/src/cmdlfem4x50.h @@ -14,6 +14,8 @@ #include"common.h" #include "em4x50.h" +int CmdLFEM4X50(const char *Cmd); + int read_em4x50_uid(void); bool detect_4x50_block(void); int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 4d85a78fd..4e1dc76cd 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -174,30 +174,11 @@ lf simfsk lf simpsk lf simbidir lf sniff -lf tune -lf em 410x_demod -lf em 410x_read -lf em 410x_sim -lf em 410x_brute -lf em 410x_watch -lf em 410x_spoof -lf em 410x_clone -lf em 4x05_demod -lf em 4x05_dump -lf em 4x05_wipe -lf em 4x05_info -lf em 4x05_read -lf em 4x05_write -lf em 4x50_dump -lf em 4x50_info -lf em 4x50_write -lf em 4x50_write_password -lf em 4x50_read -lf em 4x50_wipe -lf hitag info +lf em 410x +lf em 4x05 +lf em 4x50 lf hitag reader lf hitag sim -lf hitag sniff lf hitag writer lf hitag dump lf hitag cc diff --git a/doc/commands.md b/doc/commands.md index 6a9b61b40..f496ef3fe 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -572,34 +572,14 @@ Check column "offline" for their availability. ### lf em - { EM4X CHIPs & RFIDs... } + { EM CHIPs & RFIDs... } |command |offline |description |------- |------- |----------- |`lf em help `|Y |`This help` -|`lf em 410x_demod `|Y |`demodulate a EM410x tag from the GraphBuffer` -|`lf em 410x_read `|N |`attempt to read and extract tag data` -|`lf em 410x_sim `|N |`simulate EM410x tag` -|`lf em 410x_brute `|N |`reader bruteforce attack by simulating EM410x tags` -|`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` -|`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` -|`lf em 410x_clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag` -|`lf em 4x05_chk `|N |`Check passwords from dictionary` -|`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer` -|`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag` -|`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag` -|`lf em 4x05_info `|N |`tag information EM4x05/EM4x69` -|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69` -|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69` -|`lf em 4x05_unlock `|N |`execute tear off against EM4x05/EM4x69` -|`lf em 4x05_sniff `|Y |`Attempt to recover em4x05 commands from sample buffer` -|`lf em 4x05_brute `|N |`Bruteforce password` -|`lf em 4x50_dump `|N |`dump EM4x50 tag` -|`lf em 4x50_info `|N |`tag information EM4x50` -|`lf em 4x50_write `|N |`write word data to EM4x50` -|`lf em 4x50_write_password`|N |`change password of EM4x50 tag` -|`lf em 4x50_read `|N |`read word data from EM4x50` -|`lf em 4x50_wipe `|N |`wipe data from EM4x50` +|`lf em 410x `|Y |`EM 410x commands...` +|`lf em 4x05 `|Y |`EM 4x05 commands...` +|`lf em 4x50 `|Y |`EM 4x50 commands...` ### lf fdxb From 0f5442134555e26aed197dda9f70b8dbd4c4be27 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 00:13:37 +0100 Subject: [PATCH 02/15] forgot a file --- client/src/cmdlfem410x.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 client/src/cmdlfem410x.h diff --git a/client/src/cmdlfem410x.h b/client/src/cmdlfem410x.h new file mode 100644 index 000000000..62d35cf55 --- /dev/null +++ b/client/src/cmdlfem410x.h @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// 2016, 2017 marshmellow, iceman +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency EM 410x commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFEM410X_H__ +#define CMDLFEM410X_H__ + +#include "common.h" + +int CmdLFEM410X(const char *Cmd); + +int demodEM410x(bool verbose); +void printEM410x(uint32_t hi, uint64_t id); + +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo); +int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose); + +#endif From f22c0e87bcabdf54748984b8c88e1dea637f7a8d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 00:14:18 +0100 Subject: [PATCH 03/15] forgot a file --- client/src/cmdlfem410x.c | 653 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 653 insertions(+) create mode 100644 client/src/cmdlfem410x.c diff --git a/client/src/cmdlfem410x.c b/client/src/cmdlfem410x.c new file mode 100644 index 000000000..ef35e95a0 --- /dev/null +++ b/client/src/cmdlfem410x.c @@ -0,0 +1,653 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency EM4x commands +//----------------------------------------------------------------------------- + +#include "cmdlfem410x.h" +#include "cmdlfem4x50.h" + +#include +#include +#include +#include +#include + +#include "fileutils.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "commonutil.h" +#include "common.h" +#include "util_posix.h" +#include "protocols.h" +#include "ui.h" +#include "proxgui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" +#include "generator.h" +#include "cliparser.h" +#include "cmdhw.h" + +static uint64_t g_em410xid = 0; + +static int CmdHelp(const char *Cmd); + +//////////////// 410x commands +static int usage_lf_em410x_demod(void) { + PrintAndLogEx(NORMAL, "Usage: lf em 410x_demod [h] [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " clock - set clock as integer, optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " <0|1> - 0 normal output, 1 for invert output"); + PrintAndLogEx(NORMAL, " maxerror - set maximum allowed errors, default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod") " = demod an EM410x Tag ID from GraphBuffer"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 32") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 32 1") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 1") " = demod an EM410x Tag ID from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_demod 64 1 0") " = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"); + return PM3_SUCCESS; +} +static int usage_lf_em410x_watch(void) { + PrintAndLogEx(NORMAL, "Enables IOProx compatible reader mode printing details of scanned tags."); + PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 410x_watch"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_watch")); + return PM3_SUCCESS; +} + +static int usage_lf_em410x_clone(void) { + PrintAndLogEx(NORMAL, "Writes EM410x ID to a T55x7 or Q5/T5555 tag"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 410x_clone [h] [clock]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " - ID number"); + PrintAndLogEx(NORMAL, " - 0|1 0 = Q5/T5555, 1 = T55x7"); + PrintAndLogEx(NORMAL, " - 16|32|40|64, optional, set R/F clock rate, defaults to 64"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_clone 0F0368568B 1") " = write ID to t55x7 card"); + return PM3_SUCCESS; +} +static int usage_lf_em410x_ws(void) { + PrintAndLogEx(NORMAL, "Watch 'nd Spoof, activates reader, waits until a EM410x tag gets presented then it starts simulating the found UID"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 410x_spoof [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_spoof")); + return PM3_SUCCESS; +} +static int usage_lf_em410x_sim(void) { + PrintAndLogEx(NORMAL, "Simulating EM410x tag"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 410x_sim [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " uid - uid (10 HEX symbols)"); + PrintAndLogEx(NORMAL, " clock - clock (32|64) (optional)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_sim 0F0368568B")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_sim 0F0368568B 32")); + return PM3_SUCCESS; +} +static int usage_lf_em410x_brute(void) { + PrintAndLogEx(NORMAL, "Bruteforcing by emulating EM410x tag"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 410x_brute [h] ids.txt [d 2000] [c clock]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " ids.txt - file with UIDs in HEX format, one per line"); + PrintAndLogEx(NORMAL, " d (2000) - pause delay in milliseconds between UIDs simulation, default 1000 ms (optional)"); + PrintAndLogEx(NORMAL, " c (32) - clock (32|64), default 64 (optional)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt c 32")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt d 3000")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_brute ids.txt d 3000 c 32")); + return PM3_SUCCESS; +} + +/* Read the ID of an EM410x tag. + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ + +// Construct the graph for emulating an EM410X tag +static void ConstructEM410xEmulGraph(const char *uid, const uint8_t clock) { + + int i, j, binary[4], parity[4]; + uint32_t n; + /* clear our graph */ + ClearGraph(true); + + /* write 16 zero bit sledge */ + for (i = 0; i < 20; i++) + AppendGraph(false, clock, 0); + + /* write 9 start bits */ + for (i = 0; i < 9; i++) + AppendGraph(false, clock, 1); + + /* for each hex char */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) { + /* read each hex char */ + sscanf(&uid[i], "%1x", &n); + for (j = 3; j >= 0; j--, n /= 2) + binary[j] = n % 2; + + /* append each bit */ + AppendGraph(false, clock, binary[0]); + AppendGraph(false, clock, binary[1]); + AppendGraph(false, clock, binary[2]); + AppendGraph(false, clock, binary[3]); + + /* append parity bit */ + AppendGraph(false, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + + /* keep track of column parity */ + parity[0] ^= binary[0]; + parity[1] ^= binary[1]; + parity[2] ^= binary[2]; + parity[3] ^= binary[3]; + } + + /* parity columns */ + AppendGraph(false, clock, parity[0]); + AppendGraph(false, clock, parity[1]); + AppendGraph(false, clock, parity[2]); + AppendGraph(false, clock, parity[3]); + + /* stop bit */ + AppendGraph(true, clock, 0); +} + +//by marshmellow +//print 64 bit EM410x ID in multiple formats +void printEM410x(uint32_t hi, uint64_t id) { + + if (!id && !hi) return; + + PrintAndLogEx(SUCCESS, "EM410x%s pattern found", (hi) ? " XL" : ""); + + uint64_t n = 1; + uint64_t id2lo = 0; + uint8_t m, i; + for (m = 5; m > 0; m--) { + for (i = 0; i < 8; i++) { + id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); + } + } + + if (hi) { + //output 88 bit em id + PrintAndLogEx(NORMAL, "\nEM TAG ID : "_YELLOW_("%06X%016" PRIX64), hi, id); + PrintAndLogEx(NORMAL, "Clock rate : "_YELLOW_("RF/%d"), g_DemodClock); + } else { + //output 40 bit em id + PrintAndLogEx(NORMAL, "\nEM TAG ID : "_YELLOW_("%010" PRIX64), id); + PrintAndLogEx(NORMAL, "Clock rate : "_YELLOW_("RF/%d"), g_DemodClock); + PrintAndLogEx(NORMAL, "\nPossible de-scramble patterns\n"); + PrintAndLogEx(NORMAL, "Unique TAG ID : %010" PRIX64, id2lo); + PrintAndLogEx(NORMAL, "HoneyWell IdentKey {"); + PrintAndLogEx(NORMAL, "DEZ 8 : %08" PRIu64, id & 0xFFFFFF); + PrintAndLogEx(NORMAL, "DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF); + PrintAndLogEx(NORMAL, "DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id >> 16LL) & 0xFFFF, (id & 0xFFFF)); + PrintAndLogEx(NORMAL, "DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id >> 32ll), (id & 0xFFFF)); + PrintAndLogEx(NORMAL, "DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF)); + PrintAndLogEx(NORMAL, "DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF)); + PrintAndLogEx(NORMAL, "DEZ 14/IK2 : %014" PRIu64, id); + PrintAndLogEx(NORMAL, "DEZ 15/IK3 : %015" PRIu64, id2lo); + PrintAndLogEx(NORMAL, "DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64, + (id2lo & 0xf000000000) >> 36, + (id2lo & 0x0f00000000) >> 32, + (id2lo & 0x00f0000000) >> 28, + (id2lo & 0x000f000000) >> 24, + (id2lo & 0x0000f00000) >> 20, + (id2lo & 0x00000f0000) >> 16, + (id2lo & 0x000000f000) >> 12, + (id2lo & 0x0000000f00) >> 8, + (id2lo & 0x00000000f0) >> 4, + (id2lo & 0x000000000f) + ); + uint64_t paxton = (((id >> 32) << 24) | (id & 0xffffff)) + 0x143e00; + PrintAndLogEx(NORMAL, "}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id & 0xFFFF), ((id >> 16LL) & 0xFF), (id & 0xFFFFFF)); + PrintAndLogEx(NORMAL, "Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton); + + uint32_t p1id = (id & 0xFFFFFF); + uint8_t arr[32] = {0x00}; + int j = 23; + for (int k = 0 ; k < 24; ++k, --j) { + arr[k] = (p1id >> k) & 1; + } + + uint32_t p1 = 0; + + p1 |= arr[23] << 21; + p1 |= arr[22] << 23; + p1 |= arr[21] << 20; + p1 |= arr[20] << 22; + + p1 |= arr[19] << 18; + p1 |= arr[18] << 16; + p1 |= arr[17] << 19; + p1 |= arr[16] << 17; + + p1 |= arr[15] << 13; + p1 |= arr[14] << 15; + p1 |= arr[13] << 12; + p1 |= arr[12] << 14; + + p1 |= arr[11] << 6; + p1 |= arr[10] << 2; + p1 |= arr[9] << 7; + p1 |= arr[8] << 1; + + p1 |= arr[7] << 0; + p1 |= arr[6] << 8; + p1 |= arr[5] << 11; + p1 |= arr[4] << 3; + + p1 |= arr[3] << 10; + p1 |= arr[2] << 4; + p1 |= arr[1] << 5; + p1 |= arr[0] << 9; + PrintAndLogEx(NORMAL, "Pattern 1 : %d [0x%X]", p1, p1); + + uint16_t sebury1 = id & 0xFFFF; + uint8_t sebury2 = (id >> 16) & 0x7F; + uint32_t sebury3 = id & 0x7FFFFF; + PrintAndLogEx(NORMAL, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); + } +} +/* Read the ID of an EM410x tag. + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) { + size_t idx = 0; + uint8_t bits[512] = {0}; + size_t size = sizeof(bits); + if (!getDemodBuff(bits, &size)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod"); + return PM3_ESOFT; + } + + int ans = Em410xDecode(bits, &size, &idx, hi, lo); + if (ans < 0) { + + if (ans == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod"); + else if (ans == -4) + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found"); + else if (ans == -5) + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size); + else if (ans == -6) + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x parity failed"); + + return PM3_ESOFT; + } + if (!lo && !hi) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x decoded to all zeros"); + return PM3_ESOFT; + } + + //set GraphBuffer for clone or sim command + setDemodBuff(DemodBuffer, (size == 40) ? 64 : 128, idx + 1); + setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock)); + + PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing Demod Buffer:", idx, size); + if (g_debugMode) { + printDemodBuff(0, false, false, true); + } + + if (verbose) + printEM410x(*hi, *lo); + + return PM3_SUCCESS; +} + +int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) { + bool st = true; + + // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again + if (isGraphBitstream()) { + convertGraphFromBitstream(); + } + if (ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, false, false, 1, &st) != PM3_SUCCESS) + return PM3_ESOFT; + return AskEm410xDecode(verbose, hi, lo); +} + +// this read loops on device side. +// uses the demod in lfops.c +static int CmdEM410xWatch(const char *Cmd) { + uint8_t c = tolower(param_getchar(Cmd, 0)); + if (c == 'h') return usage_lf_em410x_watch(); + + PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on antenna"); + PrintAndLogEx(INFO, "Press pm3-button to stop reading cards"); + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM410X_WATCH, NULL, 0); + PacketResponseNG resp; + WaitForResponse(CMD_LF_EM410X_WATCH, &resp); + PrintAndLogEx(INFO, "Done"); + return resp.status; +} + +//by marshmellow +//takes 3 arguments - clock, invert and maxErr as integers +//attempts to demodulate ask while decoding manchester +//prints binary found and saves in graphbuffer for further commands +int demodEM410x(bool verbose) { + (void) verbose; // unused so far + uint32_t hi = 0; + uint64_t lo = 0; + return AskEm410xDemod(0, 0, 100, 0, false, &hi, &lo, true); +} + +static int CmdEM410xDemod(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); + + uint32_t hi = 0; + uint64_t lo = 0; + int clk = 0; + int invert = 0; + int maxErr = 100; + size_t maxLen = 0; + char amp = tolower(param_getchar(Cmd, 0)); + sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); + bool amplify = amp == 'a'; + if (AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true) != PM3_SUCCESS) + return PM3_ESOFT; + + g_em410xid = lo; + return PM3_SUCCESS; +} + +// this read is the "normal" read, which download lf signal and tries to demod here. +static int CmdEM410xRead(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); + + uint32_t hi = 0; + uint64_t lo = 0; + int clk = 0; + int invert = 0; + int maxErr = 100; + size_t maxLen = 0; + char amp = tolower(param_getchar(Cmd, 0)); + sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); + bool amplify = amp == 'a'; + lf_read(false, 12288); + return AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true); +} + +// emulate an EM410X tag +static int CmdEM410xSim(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_sim(); + + uint8_t uid[5] = {0x00}; + + /* clock is 64 in EM410x tags */ + uint8_t clk = 64; + + if (param_gethex(Cmd, 0, uid, 10)) { + PrintAndLogEx(FAILED, "UID must include 10 HEX symbols"); + return PM3_EINVARG; + } + + param_getdec(Cmd, 1, &clk); + + PrintAndLogEx(SUCCESS, "Starting simulating UID "_YELLOW_("%02X%02X%02X%02X%02X")" clock: "_YELLOW_("%d"), uid[0], uid[1], uid[2], uid[3], uid[4], clk); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); + + ConstructEM410xEmulGraph(Cmd, clk); + + CmdLFSim("0"); //240 start_gap. + return PM3_SUCCESS; +} + +static int CmdEM410xBrute(const char *Cmd) { + char filename[FILE_PATH_SIZE] = {0}; + FILE *f = NULL; + char buf[11]; + uint32_t uidcnt = 0; + uint8_t stUidBlock = 20; + uint8_t *uidBlock = NULL, *p = NULL; + uint8_t uid[5] = {0x00}; + /* clock is 64 in EM410x tags */ + uint8_t clock1 = 64; + /* default pause time: 1 second */ + uint32_t delay = 1000; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_brute(); + + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 'd') { + delay = param_get32ex(Cmd, 2, 1000, 10); + param_getdec(Cmd, 4, &clock1); + } else if (cmdp == 'c') { + param_getdec(Cmd, 2, &clock1); + delay = param_get32ex(Cmd, 4, 1000, 10); + } + + int filelen = param_getstr(Cmd, 0, filename, FILE_PATH_SIZE); + if (filelen == 0) { + PrintAndLogEx(ERR, "Error: Please specify a filename"); + return PM3_EINVARG; + } + + if ((f = fopen(filename, "r")) == NULL) { + PrintAndLogEx(ERR, "Error: Could not open UIDs file ["_YELLOW_("%s")"]", filename); + return PM3_EFILE; + } + + uidBlock = calloc(stUidBlock, 5); + if (uidBlock == NULL) { + fclose(f); + return PM3_ESOFT; + } + + while (fgets(buf, sizeof(buf), f)) { + if (strlen(buf) < 10 || buf[9] == '\n') continue; + while (fgetc(f) != '\n' && !feof(f)); //goto next line + + //The line start with # is comment, skip + if (buf[0] == '#') continue; + + if (param_gethex(buf, 0, uid, 10)) { + PrintAndLogEx(FAILED, "UIDs must include 10 HEX symbols"); + free(uidBlock); + fclose(f); + return PM3_ESOFT; + } + + buf[10] = 0; + + if (stUidBlock - uidcnt < 2) { + p = realloc(uidBlock, 5 * (stUidBlock += 10)); + if (!p) { + PrintAndLogEx(WARNING, "Cannot allocate memory for UIDs"); + free(uidBlock); + fclose(f); + return PM3_ESOFT; + } + uidBlock = p; + } + memset(uidBlock + 5 * uidcnt, 0, 5); + num_to_bytes(strtoll(buf, NULL, 16), 5, uidBlock + 5 * uidcnt); + uidcnt++; + memset(buf, 0, sizeof(buf)); + } + + fclose(f); + + if (uidcnt == 0) { + PrintAndLogEx(FAILED, "No UIDs found in file"); + free(uidBlock); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Loaded "_YELLOW_("%d")" UIDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt, filename, delay); + + // loop + for (uint32_t c = 0; c < uidcnt; ++c) { + char testuid[11]; + testuid[10] = 0; + + if (kbd_enter_pressed()) { + PrintAndLogEx(WARNING, "\nAborted via keyboard!\n"); + free(uidBlock); + return PM3_EOPABORTED; + } + + sprintf(testuid, "%010" PRIX64, bytes_to_num(uidBlock + 5 * c, 5)); + PrintAndLogEx(NORMAL, "Bruteforce %d / %d: simulating UID %s, clock %d", c + 1, uidcnt, testuid, clock1); + + ConstructEM410xEmulGraph(testuid, clock1); + + CmdLFSim("0"); //240 start_gap. + + msleep(delay); + } + + free(uidBlock); + return PM3_SUCCESS; +} + +//currently only supports manchester modulations +static int CmdEM410xWatchnSpoof(const char *Cmd) { + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_ws(); + + // loops if the captured ID was in XL-format. + CmdEM410xWatch(Cmd); + PrintAndLogEx(SUCCESS, "# Replaying captured ID: "_YELLOW_("%010" PRIx64), g_em410xid); + CmdLFaskSim(""); + return PM3_SUCCESS; +} + +static int CmdEM410xClone(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 0x00 || cmdp == 'h') return usage_lf_em410x_clone(); + + uint64_t id = param_get64ex(Cmd, 0, -1, 16); + uint8_t card = param_get8ex(Cmd, 1, 0xFF, 10); + uint8_t clock1 = param_get8ex(Cmd, 2, 0, 10); + + // Check ID + if (id == 0xFFFFFFFFFFFFFFFF) { + PrintAndLogEx(ERR, "error, ID is required\n"); + usage_lf_em410x_clone(); + return PM3_EINVARG; + } + if (id >= 0x10000000000) { + PrintAndLogEx(ERR, "error, given EM410x ID is longer than 40 bits\n"); + usage_lf_em410x_clone(); + return PM3_EINVARG; + } + + // Check Card + if (card > 1) { + PrintAndLogEx(FAILED, "error, bad card type selected\n"); + usage_lf_em410x_clone(); + return PM3_EINVARG; + } + + // Check Clock + if (clock1 == 0) + clock1 = 64; + + // Allowed clock rates: 16, 32, 40 and 64 + if ((clock1 != 16) && (clock1 != 32) && (clock1 != 64) && (clock1 != 40)) { + PrintAndLogEx(FAILED, "error, clock rate" _RED_("%d")" not valid", clock1); + PrintAndLogEx(INFO, "supported clock rates: " _YELLOW_("16, 32, 40, 60") "\n"); + usage_lf_em410x_clone(); + return PM3_EINVARG; + } + + PrintAndLogEx(SUCCESS, "Writing " _YELLOW_("%s") " tag with UID 0x%010" PRIx64 " (clock rate: %d)", (card == 1) ? "T55x7" : "Q5/T5555", id, clock1); + // NOTE: We really should pass the clock in as a separate argument, but to + // provide for backwards-compatibility for older firmware, and to avoid + // having to add another argument to CMD_LF_EM410X_WRITE, we just store + // the clock rate in bits 8-15 of the card value + + struct { + uint8_t card; + uint8_t clock; + uint32_t high; + uint32_t low; + } PACKED params; + + params.card = card; + params.clock = clock1; + params.high = (uint32_t)(id >> 32); + params.low = (uint32_t)id; + + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM410X_WRITE, (uint8_t *)¶ms, sizeof(params)); + + PacketResponseNG resp; + WaitForResponse(CMD_LF_EM410X_WRITE, &resp); + switch (resp.status) { + case PM3_SUCCESS: { + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x_read`") " to verify"); + break; + } + default: { + PrintAndLogEx(WARNING, "Something went wrong"); + break; + } + } + return resp.status; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + //{"demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"}, + {"demod", CmdEM410xDemod, AlwaysAvailable, "demodulate a EM410x tag from the GraphBuffer"}, + {"read", CmdEM410xRead, IfPm3Lf, "attempt to read and extract tag data"}, + {"sim", CmdEM410xSim, IfPm3Lf, "simulate EM410x tag"}, + {"brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"}, + {"watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, + {"spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, + {"clone", CmdEM410xClone, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdLFEM410X(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} From 1b3d9fbb760dd61e48ceb6d3b0c0e639e664acaa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 00:18:11 +0100 Subject: [PATCH 04/15] adapt test --- tools/pm3_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index baf08ad5d..ad61dc13d 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -363,7 +363,7 @@ while true; do if ! CheckExecute slow "lf T55 awid 50 test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_awid_50.pm3; lf awid demod'" \ "AWID - len: 50 FC: 2001 Card: 13371337 - Wiegand: 20fa201980f92, Raw: 0128b12eb1811d7117e22111"; then break; fi if ! CheckExecute slow "lf T55 em410x test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_em410x.pm3; lf search 1'" "EM410x ID found"; then break; fi - if ! CheckExecute slow "lf T55 em410x test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_em410x.pm3; lf em 410x_demod demod'" \ + if ! CheckExecute slow "lf T55 em410x test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_em410x.pm3; lf em 410x demod'" \ "EM TAG ID : 0F0368568B"; then break; fi if ! CheckExecute slow "lf T55 fdxb_animal test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_fdxb_animal.pm3; lf search 1'" "FDX-B ID found"; then break; fi if ! CheckExecute slow "lf T55 fdxb_animal test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_fdxb_animal.pm3; lf fdxb demod'" \ From c040e63fb0220bf1c1823f8b169a8d0997305db5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 11:29:38 +0100 Subject: [PATCH 05/15] remove dublicates --- client/dictionaries/t55xx_default_pwds.dic | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/client/dictionaries/t55xx_default_pwds.dic b/client/dictionaries/t55xx_default_pwds.dic index afc00bddf..348c79e0d 100644 --- a/client/dictionaries/t55xx_default_pwds.dic +++ b/client/dictionaries/t55xx_default_pwds.dic @@ -3,7 +3,14 @@ 51243648 000D8787 19920427 -65857569 //chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) +# ZX-copy3 T55xx / EM4305 +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=40662#p40662 +# default PROX +50524F58 +# blue gun EM4305 +F9DCEBA0 +# chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) +65857569 # ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 05D73B9F # ref. http://www.proxmark.org/forum/viewtopic.php?= @@ -20,19 +27,10 @@ A5B4C3D2 00434343 44B44CAE 88661858 -# -# ZX-copy3 T55xx / EM4305 -# ref. http://www.proxmark.org/forum/viewtopic.php?pid=40662#p40662 -19920427 -84AC15E2 # paxton bullit? 575F4F4B # 50520901 -# default PROX -50524F58 -# blue gun EM4305 -F9DCEBA0 # Default pwd, simple: 00000000 11111111 From b115c82156b73cc3efa60749675214d503f47e7a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 22:25:04 +0100 Subject: [PATCH 06/15] text --- client/src/cmdwiegand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index 0e4b31b1c..c38758679 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -151,8 +151,8 @@ int CmdWiegandDecode(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdWiegandList, AlwaysAvailable, "List available wiegand formats"}, - {"encode", CmdWiegandEncode, AlwaysAvailable, "Encode to wiegand raw hex"}, - {"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to decoded wiegand format"}, + {"encode", CmdWiegandEncode, AlwaysAvailable, "Encode to wiegand raw hex (currently for HID Prox)"}, + {"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to decoded wiegand format (currently for HID Prox)"}, {NULL, NULL, NULL, NULL} }; From 7fc852be12f8facc58776a7deaf3afb52f06d693 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 22:30:15 +0100 Subject: [PATCH 07/15] text --- client/src/cmdlfhid.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 674aad661..c975eb781 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -318,16 +318,15 @@ static int CmdHIDClone(const char *Cmd) { CLIParserInit(&ctx, "lf hid clone", "clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n" "Tag must be on the antenna when issuing this command.", - "lf hid clone -r 2006ec0c86 -> HID 10301 26 bit\n" - "lf hid clone -r 2e0ec00c87 -> HID Corporate 35 bit\n" - "lf hid clone -r 01f0760643c3 -> HID P10001 40 bit\n" - "lf hid clone -r 01400076000c86 -> HID Corporate 48 bit\n" - "lf hid clone -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n" + "lf hid clone -r 2006ec0c86 -> write raw value (HID 10301 26 bit)\n" + "lf hid clone -r 2e0ec00c87 -> write raw value (HID Corporate 35 bit)\n" + "lf hid clone -r 01f0760643c3 -> write raw value (HID P10001 40 bit)\n" + "lf hid clone -r 01400076000c86 -> write raw value (HID Corporate 48 bit)\n" + "lf hid clone -w H10301 --fc 118 --cn 1603 -> write raw value (HID 10301 26 bit)\n" "lf hid clone -w H10301 --fc 118 --cn 1603 --q5 -> HID 10301 26 bit, encode for Q5/T5555 tag\n" "lf hid clone -w H10301 --fc 118 --cn 1603 --em -> HID 10301 26 bit, encode for EM4305/4469" ); - void *argtable[] = { arg_param_begin, arg_str0("w", "wiegand", "", "see " _YELLOW_("`wiegand list`") " for available formats"), From 4830bf7fec7408509f02704e433ab3a33cb22874 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 22:41:24 +0100 Subject: [PATCH 08/15] lf hid brute - fix param --- client/src/cmdlfhid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index c975eb781..e507da53b 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -464,13 +464,14 @@ static int CmdHIDBrute(const char *Cmd) { "lf hid brute -w H10301 --fc 224\n" "lf hid brute -w H10301 --fc 21 -d 2000\n" "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000\n" + "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up -v\n" ); void *argtable[] = { arg_param_begin, arg_lit0("v", "verbose", "verbose logging, show all tries"), arg_str1("w", "wiegand", "", "see " _YELLOW_("`wiegand list`") " for available formats"), - arg_int0(NULL, "fn", "", "facility code"), + arg_int0(NULL, "fc", "", "facility code"), arg_int0(NULL, "cn", "", "card number to start with"), arg_int0("i", "issue", "", "issue level"), arg_int0("o", "oem", "", "OEM code"), From 2dc27cf2b7b00f578c5c8db4c49b267c781fbe66 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 22:42:52 +0100 Subject: [PATCH 09/15] fix double.. --- client/src/cmdlfhid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index e507da53b..d0acb2924 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -464,7 +464,7 @@ static int CmdHIDBrute(const char *Cmd) { "lf hid brute -w H10301 --fc 224\n" "lf hid brute -w H10301 --fc 21 -d 2000\n" "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000\n" - "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up -v\n" + "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up\n" ); void *argtable[] = { From 80fd00c104b715917cf176c2438cf6c4d83b4aa1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 22:59:57 +0100 Subject: [PATCH 10/15] text --- client/src/cmdlfhid.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index d0acb2924..52f777967 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -63,8 +63,14 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo return PM3_ESOFT; } - if (verbose) - PrintAndLogEx(INFO, "Trying FC: %u; CN: %"PRIu64"; Issue level: %u; OEM: %u", card->FacilityCode, card->CardNumber, card->IssueLevel, card->OEM); + if (verbose) { + PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u") + , card->FacilityCode + , card->CardNumber + , card->IssueLevel + , card->OEM + ); + } lf_hidsim_t payload; payload.hi2 = packed.Top; @@ -517,20 +523,20 @@ static int CmdHIDBrute(const char *Cmd) { PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber); switch (direction) { case 0: - PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH")); + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH") " delay " _YELLOW_("%d"), delay); break; case 1: - PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP")); + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP") " delay " _YELLOW_("%d"), delay); break; case 2: - PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN")); + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN") " delay " _YELLOW_("%d"), delay); break; default: break; } } - PrintAndLogEx(INFO, "Brute-forcing HID reader"); - PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press `enter` to exit"); + PrintAndLogEx(INFO, "Started brute-forcing HID Prox reader"); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press " _GREEN_("``") " to exit"); // copy values to low. cn_low = cn_hi; @@ -556,7 +562,9 @@ static int CmdHIDBrute(const char *Cmd) { if (direction != 2) { if (cn_hi.CardNumber < 0xFFFF) { cn_hi.CardNumber++; - if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) { + return PM3_ESOFT; + } } else { fin_hi = true; } @@ -566,7 +574,9 @@ static int CmdHIDBrute(const char *Cmd) { if (direction != 1) { if (cn_low.CardNumber > 0) { cn_low.CardNumber--; - if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) { + return PM3_ESOFT; + } } else { fin_low = true; } From c25eb722dc7161dee9cce288c8fffa798b6a423e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 23:16:15 +0100 Subject: [PATCH 11/15] lf hid brute - set fmtlen.. --- client/src/cmdlfhid.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 52f777967..3e10def56 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -60,7 +60,7 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo if (HIDPack(format_idx, card, &packed) == false) { PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format."); - return PM3_ESOFT; + return PM3_ESOFT; } if (verbose) { @@ -76,6 +76,7 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo payload.hi2 = packed.Top; payload.hi = packed.Mid; payload.lo = packed.Bot; + payload.longFMT = (packed.Mid > 0xFFF); clearCommandBuffer(); @@ -246,8 +247,8 @@ static int CmdHIDSim(const char *Cmd) { arg_str0("w", "wiegand", "", "see " _YELLOW_("`wiegand list`") " for available formats"), arg_u64_0(NULL, "fc", "", "facility code"), arg_u64_0(NULL, "cn", "", "card number"), - arg_int0("i", NULL, "", "issue level"), - arg_int0("o", "oem", "", "OEM code"), + arg_u64_0("i", NULL, "", "issue level"), + arg_u64_0("o", "oem", "", "OEM code"), arg_strx0("r", "raw", "", "raw bytes"), arg_param_end }; @@ -477,11 +478,11 @@ static int CmdHIDBrute(const char *Cmd) { arg_param_begin, arg_lit0("v", "verbose", "verbose logging, show all tries"), arg_str1("w", "wiegand", "", "see " _YELLOW_("`wiegand list`") " for available formats"), - arg_int0(NULL, "fc", "", "facility code"), - arg_int0(NULL, "cn", "", "card number to start with"), - arg_int0("i", "issue", "", "issue level"), - arg_int0("o", "oem", "", "OEM code"), - arg_int0("d", "delay", "", "delay betweens attempts in ms. Default 1000ms"), + arg_u64_0(NULL, "fc", "", "facility code"), + arg_u64_0(NULL, "cn", "", "card number to start with"), + arg_u64_0("i", "issue", "", "issue level"), + arg_u64_0("o", "oem", "", "OEM code"), + 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_param_end @@ -499,11 +500,11 @@ static int CmdHIDBrute(const char *Cmd) { return PM3_EINVARG; } - cn_hi.FacilityCode = arg_get_int_def(ctx, 3, 0); - cn_hi.CardNumber = arg_get_int_def(ctx, 4, 0); - cn_hi.IssueLevel = arg_get_int_def(ctx, 5, 0); - cn_hi.OEM = arg_get_int_def(ctx, 6, 0); - delay = arg_get_int_def(ctx, 7, 1000); + cn_hi.FacilityCode = arg_get_u32_def(ctx, 3, 0); + cn_hi.CardNumber = arg_get_u32_def(ctx, 4, 0); + cn_hi.IssueLevel = arg_get_u32_def(ctx, 5, 0); + cn_hi.OEM = arg_get_u32_def(ctx, 6, 0); + delay = arg_get_u32_def(ctx, 7, 1000); if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) { direction = 0; From 4bde614006b97032cae63789329040ac1872d779 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 23:32:47 +0100 Subject: [PATCH 12/15] text --- client/src/cmdlfindala.c | 29 +++++++++++++++-------------- client/src/cmdlfio.c | 28 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index e0ca3d74e..6d2c37905 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -84,7 +84,7 @@ static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) { dest[i / 8] = bytebits_to_byte(template + i, 8); } - PrintAndLogEx(INFO, "Heden-2L card number " _GREEN_("%u"), cardnumber); + PrintAndLogEx(INFO, "Heden-2L card number %u", cardnumber); } static void decodeHeden2L(uint8_t *bits) { @@ -109,7 +109,7 @@ static void decodeHeden2L(uint8_t *bits) { if (bits[offset + 7]) cardnumber += 16384; if (bits[offset + 23]) cardnumber += 32768; - PrintAndLogEx(SUCCESS, "\tHeden-2L | " _GREEN_("%u"), cardnumber); + PrintAndLogEx(SUCCESS, " Heden-2L | %u", cardnumber); } // Indala 26 bit decode @@ -206,8 +206,8 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) { ); PrintAndLogEx(SUCCESS, "Possible de-scramble patterns"); - PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", p1, p1); - PrintAndLogEx(SUCCESS, "\tInternal ID | %" PRIu64, foo); + PrintAndLogEx(SUCCESS, " Printed | __%04d__ [0x%X]", p1, p1); + PrintAndLogEx(SUCCESS, " Internal ID | %" PRIu64, foo); decodeHeden2L(DemodBuffer); } else { @@ -218,7 +218,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) { uint32_t uid7 = bytebits_to_byte(DemodBuffer + 192, 32); PrintAndLogEx( SUCCESS - , "Indala - len " _GREEN_("%zu") " Raw: %x%08x%08x%08x%08x%08x%08x" + , "Indala (len %zu) Raw: " _GREEN_("%x%08x%08x%08x%08x%08x%08x") , DemodBufferLen , uid1 , uid2 @@ -245,7 +245,7 @@ static int CmdIndalaDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala demod", - "Tries to psk demodulate the graphbuffer as Indala Prox", + "Tries to psk demodulate the graphbuffer as Indala", "lf indala demod\n" "lf indala demod --clock 32 -> demod a Indala tag from GraphBuffer using a clock of RF/32\n" "lf indala demod --clock 32 -i -> demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data\n" @@ -276,7 +276,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala altdemod", - "Tries to psk demodulate the graphbuffer as Indala Prox\n" + "Tries to psk demodulate the graphbuffer as Indala\n" "This is uses a alternative way to demodulate and was used from the beginning in the Pm3 client.\n" "It's now considered obsolete but remains because it has sometimes its advantages.", "lf indala altdemod\n" @@ -493,7 +493,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) { static int CmdIndalaReader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala reader", - "read a Indala Prox tag", + "read a Indala tag", "lf indala reader -@ -> continuous reader mode" ); @@ -527,7 +527,7 @@ static int CmdIndalaSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala sim", - "Enables simulation of IOProx card with specified facility-code and card number.\n" + "Enables simulation of Indala card with specified facility-code and card number.\n" "Simulation runs until the button is pressed or another USB command is issued.", "lf indala sim --heden 888\n" "lf indala sim --raw a0000000a0002021\n" @@ -616,7 +616,8 @@ static int CmdIndalaClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala clone", - "clone INDALA UID to T55x7 or Q5/T5555 tag", + "clone INDALA UID to T55x7 or Q5/T5555 tag\n" + _RED_("\nWarning, encoding with FC/CN doesn't always work"), "lf indala clone --heden 888\n" "lf indala clone --fc 123 --cn 1337\n" "lf indala clone -r a0000000a0002021\n" @@ -626,8 +627,8 @@ static int CmdIndalaClone(const char *Cmd) { arg_param_begin, arg_strx0("r", "raw", "", "raw bytes"), arg_int0(NULL, "heden", "", "Cardnumber for Heden 2L format"), - arg_int0(NULL, "fc", "", "Facility Code (26 bit format)"), - arg_int0(NULL, "cn", "", "Cardnumber (26 bit format)"), + arg_int0(NULL, "fc", "", "Facility Code (26 bit H10301 format)"), + arg_int0(NULL, "cn", "", "Cardnumber (26 bit H10301 format)"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_param_end @@ -769,8 +770,8 @@ static int CmdIndalaClone(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "this help"}, {"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an indala tag (PSK1) from 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 Prox tag from the antenna"}, + {"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"}, {"clone", CmdIndalaClone, IfPm3Lf, "clone Indala tag to T55x7 or Q5/T5555"}, {"sim", CmdIndalaSim, IfPm3Lf, "simulate Indala tag"}, {NULL, NULL, NULL, NULL} diff --git a/client/src/cmdlfio.c b/client/src/cmdlfio.c index b82439263..3adc0ed90 100644 --- a/client/src/cmdlfio.c +++ b/client/src/cmdlfio.c @@ -34,7 +34,7 @@ static int CmdHelp(const char *Cmd); static int CmdIOProxWatch(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf io watch", - "Enables IOProx compatible reader mode printing details.\n" + "Enables ioProx compatible reader mode printing details.\n" "By default, values are printed and logged until the button is pressed or another USB command is issued.", "lf io watch" ); @@ -57,7 +57,7 @@ static int CmdIOProxWatch(const char *Cmd) { } //IO-Prox demod - FSK RF/64 with preamble of 000000001 -//print ioprox ID and some format details +//print ioProx ID and some format details int demodIOProx(bool verbose) { (void) verbose; // unused so far int idx = 0, retval = PM3_SUCCESS; @@ -157,7 +157,7 @@ int demodIOProx(bool verbose) { static int CmdIOProxDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf io demod", - "Try to find IOProx preamble, if found decode / descramble data", + "Try to find ioProx preamble, if found decode / descramble data", "lf io demod" ); @@ -173,7 +173,7 @@ static int CmdIOProxDemod(const char *Cmd) { static int CmdIOProxReader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf io reader", - "read a IOProx tag", + "read a ioProx tag", "lf io reader -@ -> continuous reader mode" ); @@ -198,7 +198,7 @@ static int CmdIOProxSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf io sim", - "Enables simulation of IOProx card with specified facility-code and card number.\n" + "Enables simulation of ioProx card with specified facility-code and card number.\n" "Simulation runs until the button is pressed or another USB command is issued.", "lf io sim --vn 1 --fc 101 --cn 1337" ); @@ -220,10 +220,10 @@ static int CmdIOProxSim(const char *Cmd) { if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; - PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (ioProx): %u", cn); } - PrintAndLogEx(SUCCESS, "Simulating IOProx version: " _YELLOW_("%u") " FC: " _YELLOW_("%u (0x%02x)") " CN: " _YELLOW_("%u"), version, fc, fc, cn); + PrintAndLogEx(SUCCESS, "Simulating ioProx version: " _YELLOW_("%u") " FC: " _YELLOW_("%u (0x%02x)") " CN: " _YELLOW_("%u"), version, fc, fc, cn); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); uint8_t bs[64]; @@ -233,7 +233,7 @@ static int CmdIOProxSim(const char *Cmd) { PrintAndLogEx(ERR, "Error with tag bitstream generation."); return PM3_ESOFT; } - // IOProx uses: fcHigh: 10, fcLow: 8, clk: 64, invert: 1 + // ioProx uses: fcHigh: 10, fcLow: 8, clk: 64, invert: 1 // arg1 --- fcHigh<<8 + fcLow // arg2 --- Invert and clk setting // size --- 64 bits == 8 bytes @@ -259,7 +259,7 @@ static int CmdIOProxClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf io clone", - "Enables simulation of IOProx card with specified facility-code and card number.\n" + "Enables simulation of ioProx card with specified facility-code and card number.\n" "Tag must be on the antenna when issuing this command.", "lf io clone --vn 1 --fc 101 --cn 1337" ); @@ -292,7 +292,7 @@ static int CmdIOProxClone(const char *Cmd) { if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; - PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (ioProx): %u", cn); } if (getIOProxBits(version, fc, cn, bits) != PM3_SUCCESS) { @@ -317,7 +317,7 @@ static int CmdIOProxClone(const char *Cmd) { blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); - PrintAndLogEx(INFO, "Preparing to clone IOProx to " _YELLOW_("%s") " with Version: " _GREEN_("%u") " FC: " _GREEN_("%u (0x%02x)") " CN: " _GREEN_("%u") + PrintAndLogEx(INFO, "Preparing to clone ioProx to " _YELLOW_("%s") " with Version: " _GREEN_("%u") " FC: " _GREEN_("%u (0x%02x)") " CN: " _GREEN_("%u") , cardtype , version , fc @@ -339,10 +339,10 @@ static int CmdIOProxClone(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "this help"}, - {"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an IOProx tag from the GraphBuffer"}, + {"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an ioProx tag from the GraphBuffer"}, {"reader", CmdIOProxReader, IfPm3Lf, "attempt to read and extract tag data"}, - {"clone", CmdIOProxClone, IfPm3Lf, "clone IOProx tag to T55x7 or Q5/T5555"}, - {"sim", CmdIOProxSim, IfPm3Lf, "simulate IOProx tag"}, + {"clone", CmdIOProxClone, IfPm3Lf, "clone ioProx tag to T55x7 or Q5/T5555"}, + {"sim", CmdIOProxSim, IfPm3Lf, "simulate ioProx tag"}, {"watch", CmdIOProxWatch, IfPm3Lf, "continuously watch for cards. Reader mode"}, {NULL, NULL, NULL, NULL} }; From 697463fb69f8cd247472ba0d24ac5047e35ef8c0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 4 Dec 2020 23:38:40 +0100 Subject: [PATCH 13/15] text --- client/src/cmdlfindala.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index 6d2c37905..df2bd4f46 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -151,7 +151,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) { uint64_t foo = uid2 & 0x7FFFFFFF; if (DemodBufferLen == 64) { - PrintAndLogEx(SUCCESS, "Indala - len " _GREEN_("%zu") " Raw: %x%08x", DemodBufferLen, uid1, uid2); + PrintAndLogEx(SUCCESS, "Indala (len %zu) Raw: " _GREEN_("%x%08x"), DemodBufferLen, uid1, uid2); uint16_t p1 = 0; p1 |= DemodBuffer[32 + 3] << 8; @@ -616,7 +616,7 @@ static int CmdIndalaClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf indala clone", - "clone INDALA UID to T55x7 or Q5/T5555 tag\n" + "clone Indala UID to T55x7 or Q5/T5555 tag\n" _RED_("\nWarning, encoding with FC/CN doesn't always work"), "lf indala clone --heden 888\n" "lf indala clone --fc 123 --cn 1337\n" @@ -769,7 +769,7 @@ static int CmdIndalaClone(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "this help"}, - {"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an indala tag (PSK1) from GraphBuffer"}, + {"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an Indala tag (PSK1) from 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"}, {"clone", CmdIndalaClone, IfPm3Lf, "clone Indala tag to T55x7 or Q5/T5555"}, From ee3c0faee16c7707819d35c1c64a3c8c81781df1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 5 Dec 2020 13:27:39 +0100 Subject: [PATCH 14/15] hf iclass -helptexts --- client/src/cmdhficlass.c | 85 +++++++++++++++++++--------------------- client/src/cmdtrace.c | 10 ++--- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index b68081746..cd6017c8a 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -354,7 +354,7 @@ static int CmdHFiClassSniff(const char *Cmd) { WaitForResponse(CMD_HF_ICLASS_SNIFF, &resp); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass list") "` to view captured tracelog"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_iclass_mytrace") "` to save tracelog for later analysing"); return PM3_SUCCESS; } @@ -371,8 +371,8 @@ static int CmdHFiClassSim(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_int1("t", "type", NULL, "Simulation type to use"), - arg_str0(NULL, "csn", "", "Specify CSN as 8 bytes (16 hex symbols) to use with sim type 0"), + arg_int1("t", "type", "<0-4> ", "Simulation type to use"), + arg_str0(NULL, "csn", "", "Specify CSN as 8 hex bytes to use with sim type 0"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -807,7 +807,7 @@ static int CmdHFiClassESave(const char *Cmd) { saveFileJSON(filename, jsfIclass, dump, bytes, NULL); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass readtagfile ") "` to view dump file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view") "` to view dump file"); return PM3_SUCCESS; } @@ -917,7 +917,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { if (enc_data_len > 0) { if (enc_data_len != 8) { - PrintAndLogEx(ERR, "Data must be 8 bytes (16 HEX characters)"); + PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 HEX symbols)"); CLIParserFree(clictx); return PM3_EINVARG; } @@ -933,7 +933,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { if (key_len > 0) { if (key_len != 16) { - PrintAndLogEx(ERR, "Transport key must be 16 bytes (32 HEX characters)"); + PrintAndLogEx(ERR, "Transport key must be 16 hex bytes (32 HEX characters)"); CLIParserFree(clictx); return PM3_EINVARG; } @@ -1116,7 +1116,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { CLIParserInit(&clictx, "hf iclass encrypt", "3DES encrypt data\n" "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside\n" - "in the resources directory. The file should be 16 bytes binary data", + "in the resources directory. The file should be 16 hex bytes of binary data", "hf iclass encrypt -d 0102030405060708\n" "hf iclass encrypt -d 0102030405060708 -k 00112233445566778899AABBCCDDEEFF"); @@ -1135,7 +1135,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { CLIGetHexWithReturn(clictx, 1, blk_data, &blk_data_len); if (blk_data_len != 8) { - PrintAndLogEx(ERR, "Block data must be 8 bytes (16 HEX characters)"); + PrintAndLogEx(ERR, "Block data must be 8 hex bytes (16 HEX symbols)"); CLIParserFree(clictx); return PM3_EINVARG; } @@ -1149,7 +1149,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { if (key_len > 0) { if (key_len != 16) { - PrintAndLogEx(ERR, "Transport key must be 16 bytes (32 HEX characters)"); + PrintAndLogEx(ERR, "Transport key must be 16 hex ytes (32 HEX characters)"); CLIParserFree(clictx); return PM3_EINVARG; } @@ -1231,9 +1231,9 @@ static int CmdHFiClassDump(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename to save dump to"), - arg_str0("k", "key", "", "debit key as 16 hex symbols OR NR/MAC for replay"), + arg_str0("k", "key", "", "debit key or NR/MAC for replay as 8 hex bytes"), arg_int0(NULL, "ki", "", "debit key index to select key from memory 'hf iclass managekeys'"), - arg_str0(NULL, "credit", "", "credit key as 16 hex symbols"), + arg_str0(NULL, "credit", "", "credit key as 8 hex bytes"), arg_int0(NULL, "ci", "", "credit key index to select key from memory 'hf iclass managekeys'"), arg_lit0(NULL, "elite", "elite computations applied to key"), arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"), @@ -1598,18 +1598,18 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { CLIParserInit(&ctx, "hf iclass wrbl", "Write data to an iCLASS tag", "hf iclass wrbl -b 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B\n" - "hf iclass wrbl -b 27 -d AAAAAAAAAAAAAAAA -k 001122334455667B --credit\n" - "hf iclass wrbl -b 11 -d AAAAAAAAAAAAAAAA --ki 0"); + "hf iclass wrbl -b 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B --credit\n" + "hf iclass wrbl -b 10 -d AAAAAAAAAAAAAAAA --ki 0"); void *argtable[] = { arg_param_begin, - arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1("b", "block", "", "The block number to read as an integer"), - arg_str1("d", "data", "", "data to write as 16 hex symbols"), + arg_int1("b", "block", "", "The block number to read"), + arg_str1("d", "data", "", "data to write as 8 hex bytes"), arg_lit0(NULL, "credit", "key is assumed to be the credit key"), arg_lit0(NULL, "elite", "elite computations applied to key"), - arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + arg_lit0(NULL, "raw", "no computations applied to key"), arg_lit0(NULL, "nr", "replay of NR/MAC"), arg_lit0("v", "verbose", "verbose output"), arg_param_end @@ -1657,7 +1657,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { CLIGetHexWithReturn(ctx, 4, data, &data_len); if (data_len != 8) { - PrintAndLogEx(ERR, "Data must be 8 bytes (16 hex characters)"); + PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 hex symbols)"); CLIParserFree(ctx); return PM3_EINVARG; } @@ -1695,20 +1695,21 @@ static int CmdHFiClassRestore(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass restore", "Restore data from dumpfile onto a iCLASS tag", - "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 1A -k 1122334455667788 --elite\n" - "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 05 --last 19 --ki 0\n" - "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 19 --ki 0 --elite"); + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 --ki 0\n" + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 --ki 0 --elite" + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 -k 1122334455667788 --elite\n" + ); void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "specify a filename to restore"), - arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1(NULL, "first", "", "The first block number to restore as an integer"), - arg_int1(NULL, "last", "", "The last block number to restore as an integer"), + arg_int1(NULL, "first", "", "The first block number to restore"), + arg_int1(NULL, "last", "", "The last block number to restore"), arg_lit0(NULL, "credit", "key is assumed to be the credit key"), arg_lit0(NULL, "elite", "elite computations applied to key"), - arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + arg_lit0(NULL, "raw", "no computations applied to key"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; @@ -1916,12 +1917,12 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1("b", "block", "", "The block number to read as an integer"), + arg_int1("b", "block", "", "The block number to read"), arg_lit0(NULL, "credit", "key is assumed to be the credit key"), arg_lit0(NULL, "elite", "elite computations applied to key"), - arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + arg_lit0(NULL, "raw", "no computations applied to key"), arg_lit0(NULL, "nr", "replay of NR/MAC"), arg_lit0("v", "verbose", "verbose output"), arg_param_end @@ -2232,12 +2233,12 @@ static int CmdHFiClassView(const char *Cmd) { CLIParserInit(&ctx, "hf iclass view", "Print a iCLASS tag dump file", "hf iclass view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" - "hf iclass view --first 1 --file hf-iclass-AA162D30F8FF12F1-dump.bin\n"); + "hf iclass view --first 1 -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"); void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "filename of dump"), - arg_int0(NULL, "first", "", "Begin printing from this block (default block6)"), + arg_int0(NULL, "first", "", "Begin printing from this block (default block 6)"), arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), arg_lit0("v", "verbose", "verbose output"), arg_param_end @@ -2325,9 +2326,9 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0(NULL, "old", "", "Specify key as 8 bytes (16 hex symbols)"), + arg_str0(NULL, "old", "", "Specify key as 8 hex bytes"), arg_int0(NULL, "oki", "", "Old key index to select key from memory 'hf iclass managekeys'"), - arg_str0(NULL, "new", "", "Specify key as 8 bytes (16 hex symbols)"), + arg_str0(NULL, "new", "", "Specify key as 8 hex bytes"), arg_int0(NULL, "nki", "", "New key index to select key from memory 'hf iclass managekeys'"), arg_str0(NULL, "csn", "", "Specify a Card Serial Number (CSN) to diversify the key (if omitted will attempt to read a CSN)"), arg_lit0(NULL, "elite", "Elite computations applied to new key"), @@ -2500,7 +2501,7 @@ static int CmdHFiClassManageKeys(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass managekeys", "Manage iCLASS Keys in client memory", - "hf iclass managekeys --ki 0 -k 1122334455667788 -> set key\n" + "hf iclass managekeys --ki 0 -k 1122334455667788 -> set key 1122334455667788 at index 0\n" "hf iclass managekeys -f mykeys.bin --save -> save key file\n" "hf iclass managekeys -f mykeys.bin --load -> load key file\n" "hf iclass managekeys -p -> print keys"); @@ -2508,7 +2509,7 @@ static int CmdHFiClassManageKeys(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "Specify a filename to use with load or save operations"), - arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Specify key index to set key in memory"), arg_lit0(NULL, "save", "Save keys in memory to file specified by filename"), arg_lit0(NULL, "load", "Load keys to memory from file specified by filename"), @@ -2908,10 +2909,10 @@ static int CmdHFiClassLookUp(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "Dictionary file with default iclass keys"), - arg_str1(NULL, "csn", "", "Specify CSN as 8 bytes (16 hex symbols)"), - arg_str1(NULL, "epurse", "", "Specify ePurse as 8 bytes (16 hex symbols)"), + arg_str1(NULL, "csn", "", "Specify CSN as 8 hex bytes"), + arg_str1(NULL, "epurse", "", "Specify ePurse as 8 hex bytes"), arg_str1(NULL, "macs", "", "MACs"), - arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + arg_lit0(NULL, "raw", "no computations applied to key"), arg_lit0(NULL, "elite", "Elite computations applied to key"), arg_param_end }; @@ -3288,16 +3289,13 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("r", "reverse", "reverse permuted key"), - arg_str1(NULL, "key", "", "input key"), + arg_lit0("r", "reverse", "reverse permuted key"), + arg_str1(NULL, "key", "", "input key, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - bool isReverse = arg_get_lit(ctx, 1); - CLIGetHexWithReturn(ctx, 2, data, &len); - CLIParserFree(ctx); memcpy(key, data, 8); @@ -3349,7 +3347,7 @@ static command_t CommandTable[] = { {"list", CmdHFiClassList, AlwaysAvailable, " List iclass history"}, {"rdbl", CmdHFiClass_ReadBlock, IfPm3Iclass, "[options..] Read Picopass / iCLASS block"}, {"reader", CmdHFiClassReader, IfPm3Iclass, " Act like an Picopass / iCLASS reader"}, - {"restore", CmdHFiClassRestore, IfPm3Iclass, "[options..] Restore a dump file onto a Picopass / iCLASS tag"}, + {"restore", CmdHFiClassRestore, IfPm3Iclass, "[options..] Restore a dump file onto a Picopass / iCLASS tag"}, {"sniff", CmdHFiClassSniff, IfPm3Iclass, " Eavesdrop Picopass / iCLASS communication"}, {"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write Picopass / iCLASS block"}, @@ -3371,7 +3369,6 @@ static command_t CommandTable[] = { {"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage keys to use with iclass commands"}, {"permutekey", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"}, {"view", CmdHFiClassView, AlwaysAvailable, "[options..] Display content from tag dump file"}, - {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 534fbbc45..ad5b38df7 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -519,8 +519,8 @@ static int CmdTraceLoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "trace load", "Load protocol data from binary file to trace buffer\n" - "File extension is (.trace)", - "trace load -f mytracefile" + "File extension is <.trace>", + "trace load -f mytracefile -> w/o file extension" ); void *argtable[] = { @@ -555,13 +555,13 @@ static int CmdTraceSave(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "trace save", "Save protocol data from trace buffer to binary file\n" - "File extension is (.trace)", - "trace save -f mytracefile" + "File extension is <.trace>", + "trace save -f mytracefile -> w/o file extension" ); void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "", "trace file to load"), + arg_strx0("f", "file", "", "trace file to save"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 54634b33b082cfdd257c7aad336c12eb0515a7a0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 5 Dec 2020 23:51:00 +0100 Subject: [PATCH 15/15] text --- client/src/cmdlfem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/cmdlfem.c b/client/src/cmdlfem.c index fbc7ac476..a89a4e2be 100644 --- a/client/src/cmdlfem.c +++ b/client/src/cmdlfem.c @@ -12,7 +12,6 @@ #include "cmdlfem410x.h" #include "cmdlfem4x05.h" #include "cmdlfem4x50.h" - #include #include #include "cmdparser.h" // command_t @@ -23,9 +22,9 @@ static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"410x", CmdLFEM410X, AlwaysAvailable, "EM 410x commands..."}, - {"4x05", CmdLFEM4X05, AlwaysAvailable, "EM 4x05 commands..."}, - {"4x50", CmdLFEM4X50, AlwaysAvailable, "EM 4x50 commands..."}, + {"410x", CmdLFEM410X, AlwaysAvailable, "EM 4102 commands..."}, + {"4x05", CmdLFEM4X05, AlwaysAvailable, "EM 4205 / 4305 / 4369 / 4469 commands..."}, + {"4x50", CmdLFEM4X50, AlwaysAvailable, "EM 4350 / 4450 commands..."}, {NULL, NULL, NULL, NULL} };