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/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 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/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/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..a89a4e2be --- /dev/null +++ b/client/src/cmdlfem.c @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// 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 4102 commands..."}, + {"4x05", CmdLFEM4X05, AlwaysAvailable, "EM 4205 / 4305 / 4369 / 4469 commands..."}, + {"4x50", CmdLFEM4X50, AlwaysAvailable, "EM 4350 / 4450 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/cmdlfem.h b/client/src/cmdlfem.h new file mode 100644 index 000000000..c4f987b0e --- /dev/null +++ b/client/src/cmdlfem.h @@ -0,0 +1,17 @@ +//----------------------------------------------------------------------------- +// 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 EM commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFEM4X_H__ +#define CMDLFEM4X_H__ + +#include "common.h" + +int CmdLFEM(const char *Cmd); + +#endif diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem410x.c similarity index 86% rename from client/src/cmdlfem4x.c rename to client/src/cmdlfem410x.c index 83af74333..ef35e95a0 100644 --- a/client/src/cmdlfem4x.c +++ b/client/src/cmdlfem410x.c @@ -8,8 +8,7 @@ // Low frequency EM4x commands //----------------------------------------------------------------------------- -#include "cmdlfem4x.h" -#include "cmdlfem4x05.h" +#include "cmdlfem410x.h" #include "cmdlfem4x50.h" #include @@ -631,41 +630,14 @@ static int CmdEM410xClone(const char *Cmd) { 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_writepwd",CmdEM4x50WritePwd, IfPm3EM4x50, "change password of EM4x50"}, - {"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, - {"4x50_wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe EM4x50 tag"}, - {"4x50_brute", CmdEM4x50Brute, IfPm3EM4x50, "guess password of EM4x50"}, - {"4x50_login", CmdEM4x50Login, IfPm3EM4x50, "login into EM4x50"}, - {"4x50_restore",CmdEM4x50Restore, IfPm3EM4x50, "restore EM4x50 dump to tag"}, - {"4x50_sim", CmdEM4x50Sim, IfPm3EM4x50, "simulate EM4x50 tag"}, - {"4x50_reader", CmdEM4x50Reader, IfPm3EM4x50, "show standard read mode data of EM4x50"}, - {"4x50_eload", CmdEM4x50ELoad, IfPm3EM4x50, "upload dump of EM4x50 to flash memory"}, - {"4x50_esave", CmdEM4x50ESave, IfPm3EM4x50, "save flash memory to file"}, - {"4x50_chk", CmdEM4x50Chk, IfPm3EM4x50, "check passwords from dictionary"}, + //{"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} }; @@ -675,7 +647,7 @@ static int CmdHelp(const char *Cmd) { return PM3_SUCCESS; } -int CmdLFEM4X(const char *Cmd) { +int CmdLFEM410X(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } diff --git a/client/src/cmdlfem4x.h b/client/src/cmdlfem410x.h similarity index 87% rename from client/src/cmdlfem4x.h rename to client/src/cmdlfem410x.h index 34801000e..62d35cf55 100644 --- a/client/src/cmdlfem4x.h +++ b/client/src/cmdlfem410x.h @@ -5,15 +5,15 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency EM4x commands +// Low frequency EM 410x commands //----------------------------------------------------------------------------- -#ifndef CMDLFEM4X_H__ -#define CMDLFEM4X_H__ +#ifndef CMDLFEM410X_H__ +#define CMDLFEM410X_H__ #include "common.h" -int CmdLFEM4X(const char *Cmd); +int CmdLFEM410X(const char *Cmd); int demodEM410x(bool verbose); void printEM410x(uint32_t hi, uint64_t id); 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 5b9ad5796..24de8787f 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,12 @@ #include "cliparser.h" #include "cmdlfem4x50.h" +#include +#include "cmdparser.h" // command_t #include "fileutils.h" #include "commonutil.h" #include "pmflash.h" #include "cmdflashmemspiffs.h" -#include "cmdparser.h" #define BYTES2UINT32(x) ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3])) @@ -22,6 +25,8 @@ // output functions //============================================================================== +static int CmdHelp(const char *Cmd); + static void prepare_result(const uint8_t *data, int fwr, int lwr, em4x50_word_t *words) { // restructure received result in "em4x50_word_t" structure @@ -1210,3 +1215,25 @@ int CmdEM4x50Sim(const char *Cmd) { return resp.status; } + +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 2b76cb7ef..dab84ba6c 100644 --- a/client/src/cmdlfem4x50.h +++ b/client/src/cmdlfem4x50.h @@ -13,6 +13,8 @@ #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); diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 674aad661..3e10def56 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -60,16 +60,23 @@ 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) - 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; payload.hi = packed.Mid; payload.lo = packed.Bot; + payload.longFMT = (packed.Mid > 0xFFF); clearCommandBuffer(); @@ -240,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 }; @@ -318,16 +325,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"), @@ -465,17 +471,18 @@ 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\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, "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 @@ -493,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; @@ -517,20 +524,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 +563,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 +575,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; } diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index e0ca3d74e..df2bd4f46 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 @@ -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; @@ -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 @@ -768,9 +769,9 @@ 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"}, + {"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"}, {"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} }; 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); 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} }; 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 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'" \