Merge branch 'master' into update_4x50

merged 201206
This commit is contained in:
tharexde 2020-12-06 20:40:46 +01:00
commit 894d973d69
21 changed files with 502 additions and 410 deletions

View file

@ -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

View file

@ -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 \

View file

@ -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

View file

@ -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"

View file

@ -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", "<hex>", "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", "<hex>", "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>", "filename to save dump to"),
arg_str0("k", "key", "<hex>", "debit key as 16 hex symbols OR NR/MAC for replay"),
arg_str0("k", "key", "<hex>", "debit key or NR/MAC for replay as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "debit key index to select key from memory 'hf iclass managekeys'"),
arg_str0(NULL, "credit", "<hex>", "credit key as 16 hex symbols"),
arg_str0(NULL, "credit", "<hex>", "credit key as 8 hex bytes"),
arg_int0(NULL, "ci", "<dec>", "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", "<hex>", "Access key as 16 hex symbols"),
arg_str0("k", "key", "<hex>", "Access key as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_int1("b", "block", "<dec>", "The block number to read as an integer"),
arg_str1("d", "data", "<hex>", "data to write as 16 hex symbols"),
arg_int1("b", "block", "<dec>", "The block number to read"),
arg_str1("d", "data", "<hex>", "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", "<filename>", "specify a filename to restore"),
arg_str0("k", "key", "<hex>", "Access key as 16 hex symbols"),
arg_str0("k", "key", "<hex>", "Access key as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_int1(NULL, "first", "<dec>", "The first block number to restore as an integer"),
arg_int1(NULL, "last", "<dec>", "The last block number to restore as an integer"),
arg_int1(NULL, "first", "<dec>", "The first block number to restore"),
arg_int1(NULL, "last", "<dec>", "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", "<hex>", "Access key as 16 hex symbols"),
arg_str0("k", "key", "<hex>", "Access key as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_int1("b", "block", "<dec>", "The block number to read as an integer"),
arg_int1("b", "block", "<dec>", "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>", "filename of dump"),
arg_int0(NULL, "first", "<dec>", "Begin printing from this block (default block6)"),
arg_int0(NULL, "first", "<dec>", "Begin printing from this block (default block 6)"),
arg_int0(NULL, "last", "<dec>", "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", "<hex>", "Specify key as 8 bytes (16 hex symbols)"),
arg_str0(NULL, "old", "<hex>", "Specify key as 8 hex bytes"),
arg_int0(NULL, "oki", "<dec>", "Old key index to select key from memory 'hf iclass managekeys'"),
arg_str0(NULL, "new", "<hex>", "Specify key as 8 bytes (16 hex symbols)"),
arg_str0(NULL, "new", "<hex>", "Specify key as 8 hex bytes"),
arg_int0(NULL, "nki", "<dec>", "New key index to select key from memory 'hf iclass managekeys'"),
arg_str0(NULL, "csn", "<hex>", "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", "<filename>", "Specify a filename to use with load or save operations"),
arg_str0("k", "key", "<hex>", "Access key as 16 hex symbols"),
arg_str0("k", "key", "<hex>", "Access key as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "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", "<filename>", "Dictionary file with default iclass keys"),
arg_str1(NULL, "csn", "<hex>", "Specify CSN as 8 bytes (16 hex symbols)"),
arg_str1(NULL, "epurse", "<hex>", "Specify ePurse as 8 bytes (16 hex symbols)"),
arg_str1(NULL, "csn", "<hex>", "Specify CSN as 8 hex bytes"),
arg_str1(NULL, "epurse", "<hex>", "Specify ePurse as 8 hex bytes"),
arg_str1(NULL, "macs", "<hex>", "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", "<hex>", "input key"),
arg_lit0("r", "reverse", "reverse permuted key"),
arg_str1(NULL, "key", "<hex>", "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}
};

View file

@ -12,24 +12,23 @@
// Low frequency commands
//-----------------------------------------------------------------------------
#include "cmdlf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#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... }"},

40
client/src/cmdlfem.c Normal file
View file

@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2020 iceman <iceman at icesql.net>
//
// 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 <inttypes.h>
#include <stdlib.h>
#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);
}

17
client/src/cmdlfem.h Normal file
View file

@ -0,0 +1,17 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2020 iceman <iceman at icesql.net>
// 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

View file

@ -8,8 +8,7 @@
// Low frequency EM4x commands
//-----------------------------------------------------------------------------
#include "cmdlfem4x.h"
#include "cmdlfem4x05.h"
#include "cmdlfem410x.h"
#include "cmdlfem4x50.h"
#include <stdio.h>
@ -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);
}

View file

@ -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);

View file

@ -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] <pwd>");
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] <address> <pwd>");
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] <address> <data> <pwd>");
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] <pwd>");
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", "<dec>", "memory address to read. (0-15)"),
arg_str0("p", "pwd", "<hex>", "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;
void *argtable[] = {
arg_param_begin,
arg_int0("a", "addr", "<dec>", "memory address to write to. (0-13)"),
arg_str1("d", "data", "<hex>", "data to write, 4 bytes hex"),
arg_str0("p", "pwd", "<hex>", "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);
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)) {
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", "<hex>", "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", "<hex>", "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);
}

View file

@ -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 <ctype.h>
#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);
}

View file

@ -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);

View file

@ -63,13 +63,20 @@ 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;
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", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_int0("i", NULL, "<dec>", "issue level"),
arg_int0("o", "oem", "<dec>", "OEM code"),
arg_u64_0("i", NULL, "<dec>", "issue level"),
arg_u64_0("o", "oem", "<dec>", "OEM code"),
arg_strx0("r", "raw", "<hex>", "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", "<format>", "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", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_int0(NULL, "fn", "<dec>", "facility code"),
arg_int0(NULL, "cn", "<dec>", "card number to start with"),
arg_int0("i", "issue", "<dec>", "issue level"),
arg_int0("o", "oem", "<dec>", "OEM code"),
arg_int0("d", "delay", "<dec>", "delay betweens attempts in ms. Default 1000ms"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number to start with"),
arg_u64_0("i", "issue", "<dec>", "issue level"),
arg_u64_0("o", "oem", "<dec>", "OEM code"),
arg_u64_0("d", "delay", "<dec>", "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_("`<enter>`") " 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;
}

View file

@ -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", "<hex>", "raw bytes"),
arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit H10301 format)"),
arg_int0(NULL, "cn", "<decimal>", "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}

View file

@ -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}
};

View file

@ -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", "<filename>", "trace file to load"),
arg_strx0("f", "file", "<filename>", "trace file to save"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);

View file

@ -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}
};

View file

@ -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

View file

@ -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

View file

@ -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'" \