add u64_from_hex, no need to use 0x, thanks @mwalker33!\n reverse blocks when cloning for em4305/4469

This commit is contained in:
iceman1001 2020-10-21 08:42:33 +02:00
commit be8d2fbd25
6 changed files with 85 additions and 47 deletions

View file

@ -11,8 +11,10 @@
#include "cliparser.h" #include "cliparser.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <util.h> // Get color constants #include <util.h> // Get color constants
#include <ui.h> // get PrintAndLogEx #include <ui.h> // get PrintAndLogEx
#include <ctype.h> // tolower
#include <inttypes.h> // PRIu64
#ifndef ARRAYLEN #ifndef ARRAYLEN
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0])) # define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
@ -125,7 +127,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
return 0; return 0;
} }
enum ParserState { enum ParserState {
PS_FIRST, PS_FIRST,
PS_ARGUMENT, PS_ARGUMENT,
@ -272,4 +273,20 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
return 0; return 0;
} }
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
uint64_t rv = 0;
uint8_t data[8];
int datalen = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), &datalen);
if (res == 0) {
for (uint8_t i = 0; i < datalen; i++) {
rv <<= 8;
rv |= data[i];
}
} else {
rv = def;
}
return rv;
}

View file

@ -66,4 +66,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
#endif #endif

View file

@ -374,19 +374,17 @@ int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool
// fast push mode // fast push mode
conn.block_after_ACK = true; conn.block_after_ACK = true;
int res = 0;
int res = em4x05_write_word_ext(EM_CONFIG_BLOCK, pwd, use_pwd, blockdata[0]); for (int8_t i = 0; i < numblocks; i++) {
if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "(em4x05_clone_tag) Time out writing to tag");
return res;
}
for (int8_t i = 1; i < numblocks; i++) {
// Disable fast mode on last packet // Disable fast mode on last packet
if (i == numblocks - 1) { if (i == numblocks - 1) {
conn.block_after_ACK = false; conn.block_after_ACK = false;
} }
if (i != 0) {
blockdata[i] = reflect(blockdata[i], 32);
}
res = em4x05_write_word_ext(4 + i, pwd, use_pwd, blockdata[i]); res = em4x05_write_word_ext(4 + i, pwd, use_pwd, blockdata[i]);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
@ -396,19 +394,14 @@ int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool
} }
res = 0; res = 0;
if (em4x05_verify_write(EM_CONFIG_BLOCK, use_pwd, pwd, blockdata[0]) == false) { for (int8_t i = 0; i < numblocks; i++) {
res++;
}
for (int8_t i = 1; i < numblocks; i++) {
if (em4x05_verify_write(4 + i, use_pwd, pwd, blockdata[i]) == false) { if (em4x05_verify_write(4 + i, use_pwd, pwd, blockdata[i]) == false) {
res++; res++;
} }
} }
if (res == 0) { if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Success writing to tag");
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -496,19 +489,19 @@ int CmdEM4x05Dump(const char *Cmd) {
CLIParserInit(&ctx, "lf em dump", CLIParserInit(&ctx, "lf em dump",
"Dump EM4x05/EM4x69. Tag must be on antenna.", "Dump EM4x05/EM4x69. Tag must be on antenna.",
"lf em dump\n" "lf em dump\n"
"lf em dump -p 0x11223344\n" "lf em dump -p 11223344\n"
"lf em dump -f myfile -p 0x11223344" "lf em dump -f myfile -p 11223344"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_u64_0("p", "pwd", "<hex>", "password (0x00000000)"), arg_str0("p", "pwd", "<hex>", "password (00000000)"),
arg_str0("f", "file", "<filename>", "override filename prefix (optional). Default is based on UID"), arg_str0("f", "file", "<filename>", "override filename prefix (optional). Default is based on UID"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
uint64_t inputpwd = arg_get_u64_def(ctx, 1, 0xFFFFFFFFFFFFFFFF); uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 1, 0xFFFFFFFFFFFFFFFF);
int fnlen = 0; int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
@ -1139,21 +1132,22 @@ int CmdEM4x05Chk(const char *Cmd) {
CLIParserInit(&ctx, "lf em 4x05_chk", CLIParserInit(&ctx, "lf em 4x05_chk",
"This command uses a dictionary attack against EM4205/4305/4469/4569", "This command uses a dictionary attack against EM4205/4305/4469/4569",
"lf em 4x05_chk\n" "lf em 4x05_chk\n"
"lf em 4x05_chk -e 0x00000022B8 -> remember to use 0x for hex\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 -f t55xx_default_pwds -> use T55xx default dictionary"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_strx0("f", "file", "<*.dic>", "loads a default keys dictionary file <*.dic>"), arg_strx0("f", "file", "<*.dic>", "loads a default keys dictionary file <*.dic>"),
arg_u64_0("e", "em", "<EM4100>", "try the calculated password from some cloners based on EM4100 ID"), arg_str0("e", "em", "<EM4100>", "try the calculated password from some cloners based on EM4100 ID"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
int fnlen = 0; int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
uint64_t card_id = arg_get_u64_def(ctx, 2, 0);
uint64_t card_id = arg_get_u64_hexstr_def(ctx, 2, 0);
CLIParserFree(ctx); CLIParserFree(ctx);
if (strlen(filename) == 0) { if (strlen(filename) == 0) {
@ -1241,7 +1235,7 @@ int CmdEM4x05Brute(const char *Cmd) {
"Note: if you get many false positives, change position on the antenna" "Note: if you get many false positives, change position on the antenna"
"lf em 4x05_brute\n" "lf em 4x05_brute\n"
"lf em 4x05_brute -n 1 -> stop after first candidate found\n" "lf em 4x05_brute -n 1 -> stop after first candidate found\n"
"lf em 4x05_brute -s 0x000022B8 -> remember to use 0x for hex" "lf em 4x05_brute -s 000022B8 -> remember to use 0x for hex"
); );
void *argtable[] = { void *argtable[] = {
@ -1251,7 +1245,7 @@ int CmdEM4x05Brute(const char *Cmd) {
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
uint32_t start_pwd = arg_get_u64_def(ctx, 1, 0); uint32_t start_pwd = arg_get_u64_hexstr_def(ctx, 1, 0);
uint32_t n = arg_get_int_def(ctx, 2, 0); uint32_t n = arg_get_int_def(ctx, 2, 0);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -1352,7 +1346,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
arg_int0("n", NULL, NULL, "steps to skip"), arg_int0("n", NULL, NULL, "steps to skip"),
arg_int0("s", "start", "<us>", "start scan from delay (us)"), arg_int0("s", "start", "<us>", "start scan from delay (us)"),
arg_int0("e", "end", "<us>", "end scan at delay (us)"), arg_int0("e", "end", "<us>", "end scan at delay (us)"),
arg_u64_0("p", "pwd", "", "password (0x00000000)"), arg_str0("p", "pwd", "", "password (00000000)"),
arg_lit0("v", "verbose", "verbose output"), arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
@ -1360,7 +1354,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
double n = (double)arg_get_int_def(ctx, 1, 0); double n = (double)arg_get_int_def(ctx, 1, 0);
double start = (double)arg_get_int_def(ctx, 2, 2000); double start = (double)arg_get_int_def(ctx, 2, 2000);
double end = (double)arg_get_int_def(ctx, 3, 6000); double end = (double)arg_get_int_def(ctx, 3, 6000);
uint64_t inputpwd = arg_get_u64_def(ctx, 4, 0xFFFFFFFFFFFFFFFF); uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 4, 0xFFFFFFFFFFFFFFFF);
bool verbose = arg_get_lit(ctx, 5); bool verbose = arg_get_lit(ctx, 5);
CLIParserFree(ctx); CLIParserFree(ctx);

View file

@ -205,7 +205,7 @@ static int CmdKeriClone(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "lf keri clone", CLIParserInit(&ctx, "lf keri clone",
"clone a KERI tag to a T55x7, Q5/T5555 or EM4305 tag", "clone a KERI tag to a T55x7, Q5/T5555 or EM4305/4469 tag",
"lf keri clone -t i --id 12345\n" "lf keri clone -t i --id 12345\n"
"lf keri clone -t m --fc 6 --id 12345\n"); "lf keri clone -t m --fc 6 --id 12345\n");
@ -215,17 +215,20 @@ static int CmdKeriClone(const char *Cmd) {
arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"), arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"),
arg_int0(NULL, "fc", "<dec>", "Facility Code"), arg_int0(NULL, "fc", "<dec>", "Facility Code"),
arg_int1(NULL, "id", "<dec>", "Keri ID"), arg_int1(NULL, "id", "<dec>", "Keri ID"),
arg_lit0(NULL, "em4305", "specify writing to EM5405 tag"), arg_lit0(NULL, "em", "specify writing to EM4305/4469 tag"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
char cardtype[16] = {"T55x7"};
if (arg_get_lit(ctx, 1)) { if (arg_get_lit(ctx, 1)) {
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
q5 = true; q5 = true;
} }
if (arg_get_lit(ctx, 5)) { if (arg_get_lit(ctx, 5)) {
blocks[0] = EM4305_KERI_CONFIG_BLOCK; blocks[0] = EM4305_KERI_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
em4305 = true; em4305 = true;
} }
@ -258,7 +261,7 @@ static int CmdKeriClone(const char *Cmd) {
// Prepare and write to card // Prepare and write to card
// 3 LSB is ONE // 3 LSB is ONE
uint64_t data = ((uint64_t)internalid << 3) + 7; uint64_t data = ((uint64_t)internalid << 3) + 7;
PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), (q5) ? "Q5/T5555" : "T55x7", internalid); PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), cardtype, internalid);
blocks[1] = data >> 32; blocks[1] = data >> 32;
blocks[2] = data & 0xFFFFFFFF; blocks[2] = data & 0xFFFFFFFF;

View file

@ -10,23 +10,23 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdlfvisa2000.h" #include "cmdlfvisa2000.h"
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h>
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "common.h" #include "common.h"
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "comms.h" #include "comms.h"
#include "ui.h" #include "ui.h"
#include "graph.h" #include "graph.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest #include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // write verify #include "cmdlft55xx.h" // write verify
#include "cmdlfem4x05.h" //
#define BL0CK1 0x56495332 #define BL0CK1 0x56495332
@ -39,10 +39,12 @@ static int usage_lf_visa2k_clone(void) {
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID"); PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag"); PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, " <em4305> : specify writing to EM4305/4469 tag");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233")); PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555"); PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 em4305") " -- encode for EM4305/4469");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -180,18 +182,38 @@ static int CmdVisa2kClone(const char *Cmd) {
id = param_get32ex(Cmd, 0, 0, 10); id = param_get32ex(Cmd, 0, 0, 10);
//Q5 char cardtype[16] = {"T55x7"};
// Q5
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q'; bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
if (q5) if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
}
// EM4305
bool em4305 = tolower(param_getchar(Cmd, 1)) == 'e';
if (em4305) {
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
}
if (q5 && em4305) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
blocks[2] = id; blocks[2] = id;
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id); blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, (q5) ? "Q5/T5555" : "T55x7", id); PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, cardtype, id);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res;
if (em4305) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify");
return res; return res;

View file

@ -541,8 +541,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define T55XX_WRITE_TIMEOUT 1500 #define T55XX_WRITE_TIMEOUT 1500
// em4x05 & em4x69 chip configuration register definitions // em4x05 & em4x69 chip configuration register definitions
#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) #define EM4x05_GET_BITRATE(x) ((((x) & 0x3F) * 2) + 2)
#define EM4x05_SET_BITRATE(x) ((x-2)/2) #define EM4x05_SET_BITRATE(x) (((x) - 2) / 2)
#define EM4x05_MODULATION_NRZ 0x00000000 #define EM4x05_MODULATION_NRZ 0x00000000
#define EM4x05_MODULATION_MANCHESTER 0x00000040 #define EM4x05_MODULATION_MANCHESTER 0x00000040
#define EM4x05_MODULATION_BIPHASE 0x00000080 #define EM4x05_MODULATION_BIPHASE 0x00000080
@ -557,8 +557,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define EM4x05_PSK_RF_8 0x00000800 #define EM4x05_PSK_RF_8 0x00000800
#define EM4x05_MAXBLOCK_SHIFT 14 #define EM4x05_MAXBLOCK_SHIFT 14
#define EM4x05_FIRST_USER_BLOCK 5 #define EM4x05_FIRST_USER_BLOCK 5
#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode #define EM4x05_SET_NUM_BLOCKS(x) (( (x) + 4) << 14) //# of blocks sent during default read mode
#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1) #define EM4x05_GET_NUM_BLOCKS(x) ((( (x) >> 14) & 0xF) - 4)
#define EM4x05_READ_LOGIN_REQ (1 << 18) #define EM4x05_READ_LOGIN_REQ (1 << 18)
#define EM4x05_READ_HK_LOGIN_REQ (1 << 19) #define EM4x05_READ_HK_LOGIN_REQ (1 << 19)
#define EM4x05_WRITE_LOGIN_REQ (1 << 20) #define EM4x05_WRITE_LOGIN_REQ (1 << 20)