Merge pull request #58 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2020-10-19 10:13:44 +11:00 committed by GitHub
commit 3f84bf4bce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 714 additions and 399 deletions

View file

@ -970,6 +970,14 @@ static void PacketReceived(PacketCommandNG *packet) {
);
break;
}
case CMD_LF_EM4X_LOGIN: {
struct p {
uint32_t password;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EM4xLogin(payload->password);
break;
}
case CMD_LF_EM4X_READWORD: {
struct p {
uint32_t password;

View file

@ -2501,7 +2501,7 @@ static void SendForward(uint8_t fwd_bit_count) {
}
}
static void EM4xLogin(uint32_t pwd) {
static void EM4xLoginEx(uint32_t pwd) {
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
@ -2512,6 +2512,29 @@ static void EM4xLogin(uint32_t pwd) {
// 0000 0001 fail
}
void EM4xLogin(uint32_t pwd) {
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(20);
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
EM4xLoginEx(pwd);
WaitUS(400);
// We need to acquire more than needed, to help demodulators finding the proper modulation
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0);
LEDsoff();
}
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
StartTicks();
@ -2529,7 +2552,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
* 0000 1010 ok
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
@ -2539,7 +2562,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
WaitUS(400);
DoPartialAcquisition(20, false, 6000, 1000);
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -2564,7 +2587,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
* 0000 1010 ok.
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
@ -2607,7 +2630,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
* 0000 1010 ok.
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);

View file

@ -56,6 +56,7 @@ void T55xxDangerousRawTest(uint8_t *data);
void TurnReadLFOn(uint32_t delay);
void EM4xLogin(uint32_t pwd);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);

View file

@ -203,34 +203,33 @@ int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtab
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
*datalen = 0;
int ibuf = 0;
uint8_t tmp_buf[512] = {0};
int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX
int tmplen = 0;
uint8_t tmpstr[(256 * 2) + 1] = {0};
// concat all strings in argstr into tmpstr[]
//
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
if (res) {
printf("Parameter error: buffer overflow.\n");
fflush(stdout);
return res;
}
if (ibuf == 0) {
if (tmplen == 0) {
return res;
}
switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) {
res = param_gethex_to_eol((char*)tmpstr, 0, data, maxdatalen, datalen);
switch (res) {
case 1:
printf("Parameter error: Invalid HEX value.\n");
fflush(stdout);
return 1;
printf("Parameter error: Invalid HEX value\n");
break;
case 2:
printf("Parameter error: parameter too large.\n");
fflush(stdout);
return 2;
printf("Parameter error: parameter too large\n");
break;
case 3:
printf("Parameter error: Hex string must have even number of digits.\n");
fflush(stdout);
return 3;
printf("Parameter error: Hex string must have EVEN number of digits\n");
break;
}
return 0;
fflush(stdout);
return res;
}
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
@ -238,26 +237,37 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
if (!argstr->count)
return 0;
uint8_t tmp_buf[512] = {0};
uint8_t tmpstr[(256 * 2) + 1] = {0};
int ibuf = 0;
for (int i = 0; i < argstr->count; i++) {
int len = strlen(argstr->sval[i]);
memcpy(&tmp_buf[ibuf], argstr->sval[i], len);
ibuf += len;
}
tmp_buf[ibuf] = 0;
if (!ibuf)
return 0;
if (ibuf + 1 > maxdatalen) {
printf("Parameter error: string too long, expect max %i chars\n", maxdatalen - 1);
if (len > ( (sizeof(tmpstr) / 2 ) - ibuf)) {
printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2));
fflush(stdout);
return 2;
}
memcpy(data, tmp_buf, ibuf + 1);
memcpy(&tmpstr[ibuf], argstr->sval[i], len);
ibuf += len;
}
ibuf = MIN(ibuf, (sizeof(tmpstr) / 2));
tmpstr[ibuf] = 0;
if (ibuf == 0)
return 0;
if (ibuf > maxdatalen) {
printf("Parameter error: string too long (%i chars), expected MAX %i chars\n", ibuf, maxdatalen);
fflush(stdout);
return 2;
}
memcpy(data, tmpstr, ibuf + 1);
*datalen = ibuf;
return 0;
}

View file

@ -130,7 +130,6 @@ static int CmdHF14BSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b sim",
"Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI",
"hf 14b sim\n"
"hf 14b sim -u 11AA33BB"
);
@ -139,7 +138,7 @@ static int CmdHF14BSim(const char *Cmd) {
arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t pupi[4];
int n = 0;
@ -150,6 +149,9 @@ static int CmdHF14BSim(const char *Cmd) {
PrintAndLogEx(FAILED, "failed to read pupi");
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi)));
PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
return PM3_SUCCESS;

View file

@ -34,6 +34,7 @@
#include "crc16.h" // iso15 crc
#include "cmddata.h" // getsamples
#include "fileutils.h" // savefileEML
#include "cliparser.h"
#define FrameSOF Iso15693FrameSOF
#define Logic0 Iso15693Logic0
@ -209,16 +210,6 @@ const productName_t uidmapping[] = {
static int CmdHF15Help(const char *Cmd);
static int usage_15_demod(void) {
PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n"
"Gather samples with 'hf 15 read' / 'hf 15 record'");
return PM3_SUCCESS;
}
static int usage_15_samples(void) {
PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n"
"and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal");
return PM3_SUCCESS;
}
static int usage_15_info(void) {
PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n"
"command may fail, depending on tag.\n"
@ -235,36 +226,7 @@ static int usage_15_info(void) {
_YELLOW_("\thf 15 info u"));
return PM3_SUCCESS;
}
static int usage_15_record(void) {
PrintAndLogEx(NORMAL, "Record activity without enabling carrier");
return PM3_SUCCESS;
}
static int usage_15_reader(void) {
PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n"
"\n"
"Usage: hf 15 reader [h]\n"
"Options:\n"
"\th this help\n"
"\t1 read once\n"
"\n"
"Example:\n"
_YELLOW_("\thf 15 reader\n")
_YELLOW_("\thf 15 reader 1\n"));
return PM3_SUCCESS;
}
static int usage_15_sim(void) {
PrintAndLogEx(NORMAL, "Usage: hf 15 sim <UID>\n"
"\n"
"Example:\n"
_YELLOW_("\thf 15 sim E016240000000000"));
return PM3_SUCCESS;
}
static int usage_15_findafi(void) {
PrintAndLogEx(NORMAL, "This command attempts to brute force AFI of an ISO15693 tag\n"
"\n"
"Usage: hf 15 findafi");
return PM3_SUCCESS;
}
static int usage_15_writeafi(void) {
PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi <uid|u|*> <afi>\n"
"\tuid (either): \n"
@ -358,17 +320,6 @@ static int usage_15_readmulti(void) {
"\t <count> 1-6, number of pages");
return PM3_SUCCESS;
}
static int usage_15_csetuid(void) {
PrintAndLogEx(NORMAL, "Set UID for magic Chinese card (only works with such cards)\n"
"\n"
"Usage: hf 15 csetuid <uid>\n"
"Options:\n"
"\tuid : <8B hex> full UID eg E011223344556677\n"
"\n"
"Example:\n"
_YELLOW_("\thf 15 csetuid E011223344556677"));
return PM3_SUCCESS;
}
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
@ -691,17 +642,31 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t
}
// Mode 3
//helptext
static int CmdHF15Demod(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_demod();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 demod",
"Tries to demodulate / decode ISO15693, from downloaded samples.\n"
"Gather samples with 'hf 15 samples' / 'hf 15 sniff'",
"hf 15 demod\n");
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
// The sampling rate is 106.353 ksps/s, for T = 18.8 us
int i, j;
int max = 0, maxPos = 0;
int skip = 4;
if (GraphTraceLen < 1000) return PM3_ESOFT;
if (GraphTraceLen < 1000) {
PrintAndLogEx(FAILED, "Too few samples in GraphBuffer. Need more than 1000");
PrintAndLogEx(HINT, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data");
return PM3_ESOFT;
}
// First, correlate for SOF
for (i = 0; i < 1000; i++) {
@ -719,7 +684,7 @@ static int CmdHF15Demod(const char *Cmd) {
i = maxPos + ARRAYLEN(FrameSOF) / skip;
int k = 0;
uint8_t outBuf[20];
uint8_t outBuf[2048] = {0};
memset(outBuf, 0, sizeof(outBuf));
uint8_t mask = 0x01;
for (;;) {
@ -746,40 +711,80 @@ static int CmdHF15Demod(const char *Cmd) {
} else {
i += ARRAYLEN(Logic0) / skip;
}
mask <<= 1;
if (mask == 0) {
k++;
mask = 0x01;
}
if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) {
PrintAndLogEx(INFO, "ran off end!");
break;
}
if (k > 2048) {
PrintAndLogEx(INFO, "ran out of buffer");
break;
}
}
if (mask != 0x01) {
PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)");
PrintAndLogEx(INFO, " mask = %02x", mask);
}
PrintAndLogEx(INFO, "%d octets", k);
for (i = 0; i < k; i++)
PrintAndLogEx(SUCCESS, "# %2d: %02x ", i, outBuf[i]);
if ( k == 0 ) {
return PM3_SUCCESS;
}
PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2));
i = 0;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Got %d octets, decoded as following", k);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " idx | data");
PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------");
if ( k / 16 > 0) {
for (; i < k; i += 16) {
PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, 16));
}
}
uint8_t mod = (k % 16);
if (mod > 0) {
PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, mod));
}
PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------");
if (k > 2) {
PrintAndLogEx(SUCCESS, "--> CRC %04x", Crc15(outBuf, k - 2));
}
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
// * Acquire Samples as Reader (enables carrier, sends inquiry)
//helptext
static int CmdHF15Samples(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_samples();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 samples",
"Acquire samples as Reader (enables carrier, send inquiry\n"
"and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal",
"hf 15 samples");
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIParserFree(ctx);
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0);
getSamples(0, true);
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 demod") "` to decode signal");
return PM3_SUCCESS;
}
@ -1040,11 +1045,19 @@ static int CmdHF15Info(const char *Cmd) {
return PM3_SUCCESS;
}
// Record Activity without enabling carrier
//helptext
// Sniff Activity without enabling carrier
static int CmdHF15Sniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_record();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 sniff",
"Sniff activity without enabling carrier",
"hf 15 sniff\n");
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
PacketResponseNG resp;
clearCommandBuffer();
@ -1058,30 +1071,58 @@ static int CmdHF15Sniff(const char *Cmd) {
}
static int CmdHF15Reader(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_reader();
bool loop_read = (cmdp == '1') ? false : true;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 reader",
"Act as a ISO15693 reader. Look for ISO15693 tags until Enter or the pm3 button is pressed\n",
"hf 15 reader\n"
"hf 15 reader -1");
readHF15Uid(loop_read, true);
void *argtable[] = {
arg_param_begin,
arg_lit0("1", "one", "read once"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool read_once = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Starting ISO15 reader mode");
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
readHF15Uid(!read_once, true);
return PM3_SUCCESS;
}
// Simulation is still not working very good
// helptext
static int CmdHF15Sim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 sim",
"Simulate a ISO15693 tag\n",
"hf 15 sim -u E011223344556677");
void *argtable[] = {
arg_param_begin,
arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
struct {
uint8_t uid[8];
} PACKED payload;
if (param_gethex(Cmd, 0, payload.uid, 16)) {
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
CLIParserFree(ctx);
if (uidlen != 9) {
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid));
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
PacketResponseNG resp;
clearCommandBuffer();
@ -1094,17 +1135,25 @@ static int CmdHF15Sim(const char *Cmd) {
// (There is no standard way of reading the AFI, although some tags support this)
// helptext
static int CmdHF15FindAfi(const char *Cmd) {
PacketResponseNG resp;
uint32_t timeout = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 findafi",
"This command attempts to brute force AFI of an ISO15693 tag\n",
"hf 15 findafi");
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_findafi();
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "press pm3-button to cancel");
clearCommandBuffer();
PacketResponseNG resp;
SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0);
uint32_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
timeout++;
@ -1840,16 +1889,28 @@ static int CmdHF15Restore(const char *Cmd) {
*/
static int CmdHF15CSetUID(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_csetuid();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 csetuid",
"Set UID for magic Chinese card (only works with such cards)\n",
"hf 15 csetuid -u E011223344556677");
void *argtable[] = {
arg_param_begin,
arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
struct {
uint8_t uid[8];
} PACKED payload;
if (param_gethex(Cmd, 0, payload.uid, 16)) {
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
CLIParserFree(ctx);
if (uidlen != 8) {
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols got ");
return PM3_EINVARG;
}
@ -1872,9 +1933,10 @@ static int CmdHF15CSetUID(const char *Cmd) {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload));
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "getting updated card details...");

View file

@ -272,17 +272,6 @@ static int usage_hf_iclass_managekeys(void) {
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_reader(void) {
PrintAndLogEx(NORMAL, "Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass reader [h] [1]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h Show this help");
PrintAndLogEx(NORMAL, " 1 read only 1 tag");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass reader 1"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_loclass(void) {
PrintAndLogEx(NORMAL, "Execute the offline part of loclass attack");
PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of");
@ -435,57 +424,55 @@ uint8_t get_pagemap(const picopass_hdr *hdr) {
}
static void fuse_config(const picopass_hdr *hdr) {
uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]);
PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t*)&hdr->conf, 8));
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "..................... App limit", hdr->conf.app_limit);
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ Block write lock", hdr->conf.block_writelock);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... Chip", hdr->conf.chip_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... Mem", hdr->conf.mem_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " Fuses", hdr->conf.fuses);
uint8_t fuses = hdr->conf.fuses;
PrintAndLogEx(INFO, " Fuses:");
if (isset(fuses, FUSE_FPERS))
PrintAndLogEx(SUCCESS, " Mode: " _GREEN_("Personalization (programmable)"));
PrintAndLogEx(SUCCESS, " mode..... " _GREEN_("Personalization (programmable)"));
else
PrintAndLogEx(SUCCESS, " Mode: " _YELLOW_("Application (locked)"));
PrintAndLogEx(SUCCESS, " mode..... " _YELLOW_("Application (locked)"));
if (isset(fuses, FUSE_CODING1)) {
PrintAndLogEx(SUCCESS, "Coding: RFU");
PrintAndLogEx(SUCCESS, " coding.. RFU");
} else {
if (isset(fuses, FUSE_CODING0))
PrintAndLogEx(SUCCESS, "Coding: " _YELLOW_("ISO 14443-2 B / 15693"));
PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-2 B / 15693"));
else
PrintAndLogEx(SUCCESS, "Coding: " _YELLOW_("ISO 14443-B only"));
PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-B only"));
}
uint8_t pagemap = get_pagemap(hdr);
switch (pagemap) {
case 0x0:
PrintAndLogEx(INFO, " Crypt: No auth possible. Read only if RA is enabled");
PrintAndLogEx(INFO, " crypt.... No auth possible. Read only if RA is enabled");
break;
case 0x1:
PrintAndLogEx(SUCCESS, " Crypt: Non secured page");
PrintAndLogEx(SUCCESS, " crypt.... Non secured page");
break;
case 0x2:
PrintAndLogEx(INFO, " Crypt: Secured page, keys locked");
PrintAndLogEx(INFO, " crypt.... Secured page, keys locked");
break;
case 0x03:
PrintAndLogEx(SUCCESS, " Crypt: Secured page, " _GREEN_("keys not locked"));
PrintAndLogEx(SUCCESS, " crypt.... Secured page, " _GREEN_("keys not locked"));
break;
}
if (isset(fuses, FUSE_RA))
PrintAndLogEx(SUCCESS, " RA: Read access enabled");
PrintAndLogEx(SUCCESS, " RA....... Read access enabled (non-secure mode)");
else
PrintAndLogEx(INFO, " RA: Read access not enabled");
PrintAndLogEx(INFO,
"App limit " _YELLOW_("0x%02X") ", OTP " _YELLOW_("0x%02X%02X") ", Block write lock " _YELLOW_("0x%02X")
, hdr->conf.app_limit
, hdr->conf.otp[1]
, hdr->conf.otp[0]
, hdr->conf.block_writelock
);
PrintAndLogEx(INFO,
" Chip " _YELLOW_("0x%02X") ", Mem " _YELLOW_("0x%02X") ", EAS " _YELLOW_("0x%02X") ", Fuses " _YELLOW_("0x%02X")
, hdr->conf.chip_config
, hdr->conf.mem_config
, hdr->conf.eas
, hdr->conf.fuses
);
PrintAndLogEx(INFO, " RA....... Read access not enabled");
}
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) {
@ -546,19 +533,19 @@ static void mem_app_config(const picopass_hdr *hdr) {
uint8_t app2_limit = card_app2_limit[type];
uint8_t pagemap = get_pagemap(hdr);
PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------");
PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Memory") " --------------------------");
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
PrintAndLogEx(INFO, " %u KBits (%u bytes)", kb, app2_limit * 8);
PrintAndLogEx(INFO, " %u KBits ( " _YELLOW_("%u") " bytes )", kb, app2_limit * 8);
PrintAndLogEx(INFO, " Tag has not App Areas");
return;
}
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes)", kb, app_areas, (app2_limit + 1) * 8);
PrintAndLogEx(INFO, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )", kb, app_areas, (app2_limit + 1) * 8);
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit, app1_limit + 5, app1_limit + 5);
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit);
PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------");
PrintAndLogEx(INFO, "------------------------ " _CYAN_("KeyAccess") " -------------------------");
PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)");
uint8_t book = isset(mem, 0x20);
if (book) {
@ -579,18 +566,18 @@ static void mem_app_config(const picopass_hdr *hdr) {
}
static void print_picopass_info(const picopass_hdr *hdr) {
PrintAndLogEx(INFO, "------ " _CYAN_("card configuration") " ------");
PrintAndLogEx(INFO, "-------------------- " _CYAN_("card configuration") " --------------------");
fuse_config(hdr);
mem_app_config(hdr);
}
static void print_picopass_header(const picopass_hdr *hdr) {
PrintAndLogEx(INFO, "------------ " _CYAN_("card") " -------------");
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn)));
PrintAndLogEx(SUCCESS, " Config: %s (Card configuration)", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
PrintAndLogEx(SUCCESS, "E-purse: %s (Card challenge, CC)", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
PrintAndLogEx(SUCCESS, " Kd: %s (Debit key, hidden)", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
PrintAndLogEx(SUCCESS, " Kc: %s (Credit key, hidden)", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
PrintAndLogEx(INFO, "--------------------------- " _CYAN_("card") " ---------------------------");
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
PrintAndLogEx(SUCCESS, " Kd: %s Debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
PrintAndLogEx(SUCCESS, " Kc: %s Credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
PrintAndLogEx(SUCCESS, " AIA: %s Application Issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
}
static int CmdHFiClassList(const char *Cmd) {
@ -816,6 +803,8 @@ static int CmdHFiClassSim(const char *Cmd) {
case ICLASS_SIM_MODE_CSN_DEFAULT:
case ICLASS_SIM_MODE_FULL:
default: {
PrintAndLogEx(INFO, "Starting iCLASS simulation");
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
uint8_t numberOfCSNs = 0;
clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, CSN, 8);
@ -873,11 +862,25 @@ int read_iclass_csn(bool loop, bool verbose) {
}
static int CmdHFiClassReader(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_iclass_reader();
bool loop_read = (cmdp == '1') ? false : true;
return read_iclass_csn(loop_read, true);
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass reader",
"Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed\n",
"hf iclass reader\n"
"hf iclass reader -1");
void *argtable[] = {
arg_param_begin,
arg_lit0("1", "one", "read once"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool read_once = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Starting iCLASS reader mode");
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
return read_iclass_csn(!read_once, true);
}
static int CmdHFiClassELoad(const char *Cmd) {
@ -1116,22 +1119,7 @@ static int CmdHFiClassEView(const char *Cmd) {
}
PrintAndLogEx(NORMAL, "");
uint8_t *csn = dump;
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(csn, 8));
printIclassDumpContents(dump, 1, blocks, bytes);
/*
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "----+-------------------------+---------");
PrintAndLogEx(INFO, "blk | data | ascii");
PrintAndLogEx(INFO, "----+-------------------------+---------");
for (uint16_t i = 0; i < blocks; i++){
PrintAndLogEx(INFO, "%03d | %s ", i, sprint_hex_ascii(dump + (i * 8) , 8) );
}
PrintAndLogEx(INFO, "----+-------------------------+---------");
PrintAndLogEx(NORMAL, "");
*/
free(dump);
return PM3_SUCCESS;
}
@ -1285,7 +1273,6 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
saveFileEML(fptr, decrypted, decryptedlen, 8);
saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen, NULL);
PrintAndLogEx(INFO, "Following output skips CSN / block0");
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
PrintAndLogEx(NORMAL, "");
@ -1561,7 +1548,7 @@ static int CmdHFiClassDump(const char *Cmd) {
}
}
if ((use_replay + rawkey + elite) > 0) {
if ((use_replay + rawkey + elite) > 1) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true;
}
@ -1780,9 +1767,6 @@ write_dump:
PrintAndLogEx(INFO, "Reading AA2 failed. dumping AA1 data to file");
// print the dump
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8));
printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got);
// use CSN as filename
@ -1918,7 +1902,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
if (got_blockno == false)
errors = true;
if ((use_replay + rawkey + elite) > 0) {
if ((use_replay + rawkey + elite) > 1) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true;
}
@ -2250,7 +2234,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
if (got_blockno == false)
errors = true;
if ((use_replay + rawkey + elite) > 0) {
if ((use_replay + rawkey + elite) > 1) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true;
}
@ -2411,9 +2395,20 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
, filemaxblock
);
*/
uint8_t pagemap = get_pagemap(hdr);
int i = startblock;
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " blk| data | ascii |lck| info");
PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------");
PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8));
if (i != 1)
PrintAndLogEx(INFO, "....");
while (i <= endblock) {
uint8_t *blk = iclass_dump + (i * 8);
@ -2453,10 +2448,28 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
bl_lock = true;
}
PrintAndLogEx(INFO, " %c |0x%02X| %s", (bl_lock) ? 'x' : ' ', i, sprint_hex_ascii(blk, 8));
const char *lockstr = (bl_lock) ? _RED_("x") : " ";
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
const char *info_nonks[] = {"CSN", "Config", "AIA", "User"};
const char *s = info_nonks[3];
if (i < 3) {
s = info_nonks[i];
}
PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s);
} else {
const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"};
const char *s = info_ks[6];
if (i < 6) {
s = info_ks[i];
}
PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s);
}
i++;
}
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------");
PrintAndLogEx(NORMAL, "");
}
static int CmdHFiClassView(const char *Cmd) {
@ -2500,13 +2513,9 @@ static int CmdHFiClassView(const char *Cmd) {
PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") " end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock);
}
PrintAndLogEx(NORMAL, "");
print_picopass_header((picopass_hdr *) dump);
print_picopass_info((picopass_hdr *) dump);
PrintAndLogEx(NORMAL, "");
uint8_t *csn = dump;
PrintAndLogEx(INFO, "------+----+-------------------------+----------");
PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(csn, 8));
printIclassDumpContents(dump, startblock, endblock, bytes_read);
free(dump);
return PM3_SUCCESS;
@ -2682,12 +2691,15 @@ static int saveKeys(char *filename) {
static int printKeys(void) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "idx| key");
PrintAndLogEx(INFO, "---+------------------------");
for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) {
if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0)
PrintAndLogEx(INFO, "%u: %s", i, sprint_hex(iClass_Key_Table[i], 8));
PrintAndLogEx(INFO, " %u |", i);
else
PrintAndLogEx(INFO, "%u: "_YELLOW_("%s"), i, sprint_hex(iClass_Key_Table[i], 8));
PrintAndLogEx(INFO, " %u | " _YELLOW_("%s"), i, sprint_hex(iClass_Key_Table[i], 8));
}
PrintAndLogEx(INFO, "---+------------------------");
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
@ -2805,105 +2817,15 @@ static void add_key(uint8_t *key) {
}
}
static int CmdHFiClassCheckKeys(const char *Cmd) {
// empty string
if (strlen(Cmd) == 0) return usage_hf_iclass_chk();
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// elite key, raw key, standard key
bool use_elite = false;
bool use_raw = false;
bool use_credit_key = false;
bool found_key = false;
//bool found_credit = false;
bool got_csn = false;
bool errors = false;
uint8_t cmdp = 0x00;
char filename[FILE_PATH_SIZE] = {0};
uint8_t fileNameLen = 0;
uint64_t t1 = msclock();
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_iclass_chk();
case 'f':
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
if (fileNameLen < 1) {
PrintAndLogEx(WARNING, _RED_("no filename found after f"));
errors = true;
}
cmdp += 2;
break;
case 'e':
use_elite = true;
cmdp++;
break;
case 'c':
use_credit_key = true;
cmdp++;
break;
case 'r':
use_raw = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors) return usage_hf_iclass_chk();
uint8_t *keyBlock = NULL;
uint32_t keycount = 0;
// load keys
int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount);
if (res != PM3_SUCCESS || keycount == 0) {
free(keyBlock);
return res;
}
/*
static int iclass_chk_keys(uint8_t *keyBlock, uint32_t keycount) {
iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t));
if (!pre) {
free(keyBlock);
if (pre == NULL) {
return PM3_EMALLOC;
}
// Get CSN / UID and CCNR
PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR...");
for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) {
got_csn = select_only(CSN, CCNR, false);
if (got_csn == false)
PrintAndLogEx(WARNING, "one more try");
}
if (got_csn == false) {
PrintAndLogEx(WARNING, "Tried 10 times. Can't select card, aborting...");
free(keyBlock);
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(CSN, sizeof(CSN)));
PrintAndLogEx(SUCCESS, " CCNR: " _GREEN_("%s"), sprint_hex(CCNR, sizeof(CCNR)));
PrintAndLogEx(SUCCESS, "Generating diversified keys %s", (use_elite || use_raw) ? NOLF : "");
if (use_elite)
PrintAndLogEx(NORMAL, "using " _YELLOW_("elite algo"));
if (use_raw)
PrintAndLogEx(NORMAL, "using " _YELLOW_("raw mode"));
GenerateMacFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, pre);
PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", (use_credit_key) ? "CREDIT" : "DEBIT");
// max 42 keys inside USB_COMMAND. 512/4 = 103 mac
uint32_t chunksize = keycount > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycount;
bool lastChunk = false;
@ -2987,7 +2909,195 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
break;
}
} // end chunks of keys
}
return PM3_SUCCESS;
}
*/
static int CmdHFiClassCheckKeys(const char *Cmd) {
// empty string
if (strlen(Cmd) == 0) return usage_hf_iclass_chk();
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// elite key, raw key, standard key
bool use_elite = false;
bool use_raw = false;
bool use_credit_key = false;
bool found_key = false;
//bool found_credit = false;
bool got_csn = false;
bool errors = false;
uint8_t cmdp = 0x00;
char filename[FILE_PATH_SIZE] = {0};
uint8_t fileNameLen = 0;
uint64_t t1 = msclock();
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_iclass_chk();
case 'f':
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
if (fileNameLen < 1) {
PrintAndLogEx(WARNING, _RED_("no filename found after f"));
errors = true;
}
cmdp += 2;
break;
case 'e':
use_elite = true;
cmdp++;
break;
case 'c':
use_credit_key = true;
cmdp++;
break;
case 'r':
use_raw = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors) return usage_hf_iclass_chk();
uint8_t *keyBlock = NULL;
uint32_t keycount = 0;
// load keys
int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount);
if (res != PM3_SUCCESS || keycount == 0) {
free(keyBlock);
return res;
}
// Get CSN / UID and CCNR
PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR...");
for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) {
got_csn = select_only(CSN, CCNR, false);
if (got_csn == false)
PrintAndLogEx(WARNING, "one more try");
}
if (got_csn == false) {
PrintAndLogEx(WARNING, "Tried 10 times. Can't select card, aborting...");
free(keyBlock);
DropField();
return PM3_ESOFT;
}
iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t));
if (pre == NULL) {
return PM3_EMALLOC;
}
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(CSN, sizeof(CSN)));
PrintAndLogEx(SUCCESS, " CCNR: " _GREEN_("%s"), sprint_hex(CCNR, sizeof(CCNR)));
PrintAndLogEx(SUCCESS, "Generating diversified keys %s", (use_elite || use_raw) ? NOLF : "");
if (use_elite)
PrintAndLogEx(NORMAL, "using " _YELLOW_("elite algo"));
if (use_raw)
PrintAndLogEx(NORMAL, "using " _YELLOW_("raw mode"));
GenerateMacFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, pre);
PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", (use_credit_key) ? "CREDIT" : "DEBIT");
// max 42 keys inside USB_COMMAND. 512/4 = 103 mac
uint32_t chunksize = keycount > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycount;
bool lastChunk = false;
// fast push mode
conn.block_after_ACK = true;
// keep track of position of found key
uint8_t found_offset = 0;
uint32_t key_offset = 0;
// main keychunk loop
for (key_offset = 0; key_offset < keycount; key_offset += chunksize) {
uint64_t t2 = msclock();
uint8_t timeout = 0;
if (kbd_enter_pressed()) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "Aborted via keyboard!");
goto out;
}
uint32_t keys = ((keycount - key_offset) > chunksize) ? chunksize : keycount - key_offset;
// last chunk?
if (keys == keycount - key_offset) {
lastChunk = true;
// Disable fast mode on last command
conn.block_after_ACK = false;
}
uint32_t flags = lastChunk << 8;
// bit 16
// - 1 indicates credit key
// - 0 indicates debit key (default)
flags |= (use_credit_key << 16);
clearCommandBuffer();
SendCommandOLD(CMD_HF_ICLASS_CHKKEYS, flags, keys, 0, pre + key_offset, 4 * keys);
PacketResponseNG resp;
bool looped = false;
while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) {
timeout++;
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 120) {
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
goto out;
}
looped = true;
}
if (looped)
PrintAndLogEx(NORMAL, "");
found_offset = resp.oldarg[1] & 0xFF;
uint8_t isOK = resp.oldarg[0] & 0xFF;
t2 = msclock() - t2;
switch (isOK) {
case 1: {
found_key = true;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s")
, sprint_hex(keyBlock + (key_offset + found_offset) * 8, 8)
);
break;
}
case 0: {
PrintAndLogEx(INPLACE, "Chunk [%d/%d]", key_offset, keycount);
break;
}
case 99: {
}
default: {
break;
}
}
// both keys found.
if (found_key) {
break;
}
}
out:
t1 = msclock() - t1;
@ -3288,7 +3398,6 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
uint8_t key[8] = {0};
uint8_t data[16] = {0};
bool isReverse = false;
int len = 0;
CLIParserContext *ctx;
@ -3305,7 +3414,7 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
isReverse = arg_get_lit(ctx, 1);
bool isReverse = arg_get_lit(ctx, 1);
CLIGetHexWithReturn(ctx, 2, data, &len);
@ -3327,6 +3436,28 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdHFiClassAutopwn(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass autopwn",
"Tries to check keys, if found, dump card and save file",
"hf iclass autopwn\n");
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
// Check keys.
// dump
PrintAndLogEx(INFO, "to be implemented");
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
@ -3341,7 +3472,8 @@ static command_t CommandTable[] = {
{"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write Picopass / iCLASS block"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"},
{"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"},
{"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "[options..] Automatic key recovery tool for iCLASS"},
{"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "[options..] Check keys"},
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce reader attack"},
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("simulation") " ---------------------"},

View file

@ -215,15 +215,20 @@ int infoHF_ST(void) {
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
if (resplen < 2)
if (resplen < 2) {
DropField();
return PM3_ESOFT;
}
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -235,12 +240,15 @@ int infoHF_ST(void) {
int aSELECT_FILE_CC_n = 0;
param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -248,12 +256,15 @@ int infoHF_ST(void) {
int aREAD_CC_n = 0;
param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -265,12 +276,15 @@ int infoHF_ST(void) {
int aSELECT_FILE_SYS_n = 0;
param_gethex_to_eol("00a4000c02e101", 0, aSELECT_FILE_SYS, sizeof(aSELECT_FILE_SYS), &aSELECT_FILE_SYS_n);
res = ExchangeAPDU14a(aSELECT_FILE_SYS, aSELECT_FILE_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -280,12 +294,15 @@ int infoHF_ST(void) {
int aREAD_SYS_n = 0;
param_gethex_to_eol("00b0000012", 0, aREAD_SYS, sizeof(aREAD_SYS), &aREAD_SYS_n);
res = ExchangeAPDU14a(aREAD_SYS, aREAD_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
print_st_system_info(response, resplen - 2);
@ -377,15 +394,20 @@ static int cmd_hf_st_ndef(const char *Cmd) {
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
if (resplen < 2)
if (resplen < 2) {
DropField();
return PM3_ESOFT;
}
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -397,12 +419,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
int aSELECT_FILE_NDEF_n = 0;
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -412,8 +437,10 @@ static int cmd_hf_st_ndef(const char *Cmd) {
int aVERIFY_n = 0;
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw == 0x6300) {
@ -421,12 +448,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
}
@ -437,12 +467,15 @@ static int cmd_hf_st_ndef(const char *Cmd) {
int aREAD_NDEF_n = 0;
param_gethex_to_eol("00b000001d", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -490,26 +523,24 @@ static int cmd_hf_st_protect(const char *Cmd) {
if (enable_protection && disable_protection) {
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
return PM3_EINVARG;
} else {
}
if (enable_protection) {
state[0] = 0x28;
}
if (disable_protection) {
state[0] = 0x26;
}
}
if (read_protection && write_protection) {
PrintAndLogEx(ERR, "Must specify either read or write protection, not both");
return PM3_EINVARG;
} else {
}
if (read_protection) {
state[2] = 0x01;
}
if (write_protection) {
state[2] = 0x02;
}
}
if (pwdlen != 16) {
PrintAndLogEx(ERR, "Missing 16 byte password");
@ -526,15 +557,20 @@ static int cmd_hf_st_protect(const char *Cmd) {
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
if (resplen < 2)
if (resplen < 2) {
DropField();
return PM3_ESOFT;
}
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -546,12 +582,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
int aSELECT_FILE_NDEF_n = 0;
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -562,12 +601,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -578,12 +620,15 @@ static int cmd_hf_st_protect(const char *Cmd) {
param_gethex_to_eol("00", 0, aPROTECT, sizeof(aPROTECT), &aPROTECT_n);
memcpy(aPROTECT + aPROTECT_n, state, statelen);
res = ExchangeAPDU14a(aPROTECT, aPROTECT_n + statelen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "changing protection failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -629,14 +674,13 @@ static int cmd_hf_st_pwd(const char *Cmd) {
if (change_read_password && change_write_password) {
PrintAndLogEx(ERR, "Must specify either read or write, not both");
return PM3_EINVARG;
} else {
}
if (change_read_password) {
changePwd[2] = 0x01;
}
if (change_write_password) {
changePwd[2] = 0x02;
}
}
if (pwdlen != 16) {
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
@ -657,15 +701,20 @@ static int cmd_hf_st_pwd(const char *Cmd) {
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
if (resplen < 2)
if (resplen < 2) {
DropField();
return PM3_ESOFT;
}
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -677,12 +726,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
int aSELECT_FILE_NDEF_n = 0;
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -693,12 +745,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
@ -711,12 +766,15 @@ static int cmd_hf_st_pwd(const char *Cmd) {
memcpy(aCHG_PWD + aCHG_PWD_n, changePwd, changePwdlen);
memcpy(aCHG_PWD + aCHG_PWD_n + changePwdlen, newpwd, newpwdlen);
res = ExchangeAPDU14a(aCHG_PWD, aCHG_PWD_n + changePwdlen + newpwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
if (res) {
DropField();
return res;
}
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "password change failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));

View file

@ -147,7 +147,7 @@ static bool EM_ColParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t col
return true;
}
#define EM_PREAMBLE_LEN 6
#define EM_PREAMBLE_LEN 8
// download samples from device and copy to Graphbuffer
static bool downloadSamplesEM(void) {
@ -178,15 +178,15 @@ static int doPreambleSearch(size_t *startIdx) {
return PM3_ESOFT;
}
// set size to 9 to only test first 3 positions for the preamble
// set size to 11 to only test first 3 positions for the preamble
// do not set it too long else an error preamble followed by 010 could be seen as success.
size_t size = (9 > DemodBufferLen) ? DemodBufferLen : 9;
size_t size = (11 > DemodBufferLen) ? DemodBufferLen : 11;
*startIdx = 0;
// skip first two 0 bits as they might have been missed in the demod
uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 1, 0, 1, 0};
uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 1, 0, 1, 0};
if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 1};
uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 0, 0, 1};
if (!preambleSearchEx(DemodBuffer, errpreamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %zu", *startIdx);
return PM3_ESOFT;
@ -361,6 +361,29 @@ static int demodEM4x05resp(uint32_t *word, bool onlyPreamble) {
//////////////// 4205 / 4305 commands
static int EM4x05Login_ext(uint32_t pwd) {
struct {
uint32_t password;
} PACKED payload;
payload.password = pwd;
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X_LOGIN, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X_LOGIN, &resp, 10000)) {
PrintAndLogEx(WARNING, "(EM4x05Login_ext) timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
if (downloadSamplesEM() == false) {
return PM3_ESOFT;
}
uint32_t word;
return demodEM4x05resp(&word, true);
}
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
struct {
@ -438,7 +461,6 @@ int CmdEM4x05Dump(const char *Cmd) {
if (EM4x05IsBlock0(&block0) == false)
return PM3_ESOFT;
bool needReadPwd = true;
uint8_t bytes[4] = {0};
uint32_t data[16];
@ -456,28 +478,32 @@ int CmdEM4x05Dump(const char *Cmd) {
em_tech_type_t card_type = em_get_card_type(block0);
PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(block0));
PrintAndLogEx(NORMAL, "");
if (usePwd) {
// Test first if the password is correct
status = EM4x05Login_ext(pwd);
if (status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Password is " _GREEN_("correct"));
} else if (status == PM3_EFAILED) {
PrintAndLogEx(WARNING, "Password is " _RED_("incorrect") ", will try without password");
usePwd = false;
} else if (status != PM3_EFAILED) {
PrintAndLogEx(WARNING, "Login attempt: No answer from tag");
return status;
}
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Addr | data | ascii |lck| info");
PrintAndLogEx(INFO, "-----+----------+-------+---+-----");
if ( card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) {
if (usePwd) {
// Test first if a password is required
status = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, false, &word);
if (status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Note that password doesn't seem to be needed");
needReadPwd = false;
}
}
// To flag any blocks locked we need to read blocks 14 and 15 first
// dont swap endin until we get block lock flags.
status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word);
if (status14 == PM3_SUCCESS) {
if (!usePwd)
needReadPwd = false;
if ((word & 0x00008000) != 0x00) {
lock_bits = word;
gotLockBits = true;
@ -503,14 +529,9 @@ int CmdEM4x05Dump(const char *Cmd) {
lockbit = (lock_bits >> addr) & 1;
if (addr == 2) {
if (usePwd) {
if ((needReadPwd) && (success != PM3_ESOFT)) {
data[addr] = BSWAP_32(pwd);
num_to_bytes(pwd, 4, bytes);
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
} else {
// The pwd is not needed for Login so we're not sure what's the actual content of that block
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
}
} else {
data[addr] = 0x00; // Unknown password, but not used to set to zeros
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
@ -550,21 +571,10 @@ int CmdEM4x05Dump(const char *Cmd) {
} else if (card_type == EM_4X69) {
if (usePwd) {
// Test first if a password is required
status = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, false, &word);
if (status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Note that password doesn't seem to be needed");
needReadPwd = false;
}
}
// To flag any blocks locked we need to read blocks 14 and 15 first
// dont swap endin until we get block lock flags.
status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word);
if (status14 == PM3_SUCCESS) {
if (!usePwd)
needReadPwd = false;
if ((word & 0x00008000) != 0x00) {
lock_bits = word;
gotLockBits = true;
@ -580,14 +590,9 @@ int CmdEM4x05Dump(const char *Cmd) {
lockbit = (lock_bits >> addr) & 1;
if (addr == 2) {
if (usePwd) {
if ((needReadPwd) && (success != PM3_ESOFT)) {
data[addr] = BSWAP_32(pwd);
num_to_bytes(pwd, 4, bytes);
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]);
} else {
// The pwd is not needed for Login so we're not sure what's the actual content of that block
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
}
} else {
data[addr] = 0x00; // Unknown password, but not used to set to zeros
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
@ -1100,8 +1105,6 @@ int CmdEM4x05Chk(const char *Cmd) {
}
PrintAndLogEx(NORMAL, "");
uint8_t addr = 4;
uint32_t word = 0;
bool found = false;
uint64_t t1 = msclock();
@ -1111,10 +1114,12 @@ int CmdEM4x05Chk(const char *Cmd) {
uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF);
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
int status = EM4x05ReadWord_ext(addr, pwd, true, &word);
int status = EM4x05Login_ext(pwd);
if (status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
found = true;
} else if (status != PM3_EFAILED) {
PrintAndLogEx(WARNING, "No answer from tag");
}
}
@ -1124,7 +1129,6 @@ int CmdEM4x05Chk(const char *Cmd) {
PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command");
word = 0;
uint32_t keycount = 0;
int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
@ -1153,11 +1157,13 @@ int CmdEM4x05Chk(const char *Cmd) {
PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
int status = EM4x05ReadWord_ext(addr, curr_password, 1, &word);
int status = EM4x05Login_ext(curr_password);
if (status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
found = true;
break;
} else if (status != PM3_EFAILED) {
PrintAndLogEx(WARNING, "No answer from tag");
}
}
}
@ -1351,7 +1357,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
uint32_t soon = 0;
uint32_t late = 0;
em4x05_unlock_item_t flipped[64];
em4x05_unlock_item_t flipped[64] ={{0,0}};
//
// main loop

View file

@ -156,26 +156,36 @@ static int CmdMotorolaClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf motorola clone",
"Enables cloning of Motorola card with specified uid onto T55x7\n"
"defaults to 64.",
"lf motorola clone a0000000a0002021"
"clone Motorola UID to T55x7 or Q5/T5555 tag\n"
"defaults to 64 bit format",
"lf motorola clone -r a0000000a0002021"
);
void *argtable[] = {
arg_param_begin,
arg_strx1(NULL, NULL, "<uid (hex)>", NULL),
arg_strx1("r", "raw", "<hex>", "raw bytes"),
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIGetHexWithReturn(ctx, 1, data, &datalen);
bool is_t5555 = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
//TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_FIXED | T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen));
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag");
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
if (is_t5555)
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
else
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
blocks[1] = bytes_to_num(data, 4);
blocks[2] = bytes_to_num(data + 4, 4);

View file

@ -60,7 +60,9 @@ extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char
if (getenv("DISPLAY") == NULL)
return;
#endif
#if QT_VERSION >= 0x050100
qunsetenv("SESSION_MANAGER");
#endif
main_loop_thread = new WorkerThread(script_cmds_file, script_cmd, stayInCommandLoop);
gui = new ProxGuiQT(argc, argv, main_loop_thread);
}

View file

@ -496,6 +496,7 @@ typedef struct {
#define CMD_LF_T55XX_RESET_READ 0x0216
#define CMD_LF_PCF7931_READ 0x0217
#define CMD_LF_PCF7931_WRITE 0x0223
#define CMD_LF_EM4X_LOGIN 0x0229
#define CMD_LF_EM4X_READWORD 0x0218
#define CMD_LF_EM4X_WRITEWORD 0x0219
#define CMD_LF_EM4X_PROTECTWORD 0x021B