Merge pull request #1064 from tcprst/iclass_cliparser

Iclass cliparser esave, eview - now use cliparser
This commit is contained in:
Iceman 2020-11-23 01:56:40 +01:00 committed by GitHub
commit f4f2099075
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 186 deletions

View file

@ -1179,10 +1179,10 @@ static int CmdHF14AAPDU(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )", PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )",
activateField ? "select" : "", activateField ? "select" : "",
leaveSignalON ? ", keep" : "", leaveSignalON ? ", keep" : "",
decodeTLV ? ", TLV" : "" decodeTLV ? ", TLV" : ""
); );
PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen)); PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen));
if (decodeAPDU) { if (decodeAPDU) {
@ -1217,7 +1217,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
"Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.", "Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n" "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n" "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -1347,10 +1347,10 @@ static int waitCmd(bool i_select, uint32_t timeout) {
char s[16]; char s[16];
sprintf(s, sprintf(s,
(crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"), (crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
data[len - 2], data[len - 2],
data[len - 1] data[len - 1]
); );
PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s); PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s);
} else { } else {

View file

@ -71,35 +71,6 @@ static int usage_hf_iclass_sim(void) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf_iclass_esave(void) {
PrintAndLogEx(NORMAL, "Save emulator memory to file.");
PrintAndLogEx(NORMAL, "if not filename is supplied, CSN will be used.");
PrintAndLogEx(NORMAL, "Number of bytes to download defaults to 256. Other value is 2048\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass esave [h] [f <filename>] [s <num of bytes>]\n");
PrintAndLogEx(NORMAL, "Options");
PrintAndLogEx(NORMAL, " h : Show this help");
PrintAndLogEx(NORMAL, " f <filename> : filename of dump");
PrintAndLogEx(NORMAL, " s <bytes> : (256|2048) number of bytes to save (default 256)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave"));
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave f hf-iclass-dump.bin"));
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave s 2048 f hf-iclass-dump.bin"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_eview(void) {
PrintAndLogEx(NORMAL, "It displays emulator memory");
PrintAndLogEx(NORMAL, "Number of bytes to download defaults to 256. Other value is 2048\n");
PrintAndLogEx(NORMAL, " Usage: hf iclass eview [s <num of bytes>] <v>");
PrintAndLogEx(NORMAL, " s <bytes> : (256|2048) number of bytes to save (default 256)");
PrintAndLogEx(NORMAL, " v : verbose output");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview s 2048 v"));
return PM3_SUCCESS;
}
static int usage_hf_iclass_decrypt(void) { static int usage_hf_iclass_decrypt(void) {
PrintAndLogEx(NORMAL, "3DES decrypt data\n"); PrintAndLogEx(NORMAL, "3DES decrypt data\n");
PrintAndLogEx(NORMAL, "This is naive implementation, it tries to decrypt every block after block 6."); PrintAndLogEx(NORMAL, "This is naive implementation, it tries to decrypt every block after block 6.");
@ -779,7 +750,7 @@ static int CmdHFiClassSim(const char *Cmd) {
SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, CSN, 8); SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, CSN, 8);
if (sim_type == ICLASS_SIM_MODE_FULL) if (sim_type == ICLASS_SIM_MODE_FULL)
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass esave h") "` to save the emulator memory to file"); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass esave -h") "` to save the emulator memory to file");
break; break;
} }
} }
@ -961,47 +932,36 @@ static int CmdHFiClassELoad(const char *Cmd) {
PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHFiClassESave(const char *Cmd) { static int CmdHFiClassESave(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass esave",
"Save emulator memory to file.\n"
"if filename is not supplied, CSN will be used.",
"hf iclass esave\n"
"hf iclass esave -f hf-iclass-dump\n"
"hf iclass esave -s 2048 -f hf-iclass-dump");
void *argtable[] = {
arg_param_begin,
arg_str0("f", "file", "<filename>", "filename of dumpfile"),
arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
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);
char *fnameptr = filename; char *fnameptr = filename;
int len = 0;
uint16_t bytes = 256; uint16_t bytes = arg_get_int_def(ctx, 2, 256);
bool errors = false;
uint8_t cmdp = 0; if (bytes > 4096) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes);
switch (tolower(param_getchar(Cmd, cmdp))) { bytes = 4096;
case 'h':
return usage_hf_iclass_esave();
case 'f':
len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
if (len >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
}
cmdp += 2;
break;
case 's':
bytes = param_get32ex(Cmd, cmdp + 1, 256, 10);
if (bytes > 4096) {
PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes);
bytes = 4096;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
} }
//Validations CLIParserFree(ctx);
if (errors) {
return usage_hf_iclass_esave();
}
uint8_t *dump = calloc(bytes, sizeof(uint8_t)); uint8_t *dump = calloc(bytes, sizeof(uint8_t));
if (dump == NULL) { if (dump == NULL) {
@ -1017,7 +977,7 @@ static int CmdHFiClassESave(const char *Cmd) {
} }
// user supplied filename? // user supplied filename?
if (len < 1) { if (fnlen < 1) {
fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-"); fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-");
FillFileNameByUID(fnameptr, dump, "-dump", 8); FillFileNameByUID(fnameptr, dump, "-dump", 8);
} }
@ -1032,44 +992,37 @@ static int CmdHFiClassESave(const char *Cmd) {
} }
static int CmdHFiClassEView(const char *Cmd) { static int CmdHFiClassEView(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass eview",
"Display emulator memory.\n"
"Number of bytes to download defaults to 256. Other value is 2048.",
"hf iclass eview\n"
"hf iclass eview -s 2048\n"
"hf iclass eview -s 2048 -v");
uint16_t blocks = 32, bytes = 256; void *argtable[] = {
bool errors = false, verbose = false; arg_param_begin,
uint8_t cmdp = 0; arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"),
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { arg_lit0("v", "verbose", "filename of dumpfile"),
switch (tolower(param_getchar(Cmd, cmdp))) { arg_param_end
case 'h': };
return usage_hf_iclass_eview(); CLIExecWithReturn(ctx, Cmd, argtable, true);
case 's':
bytes = param_get32ex(Cmd, cmdp + 1, 256, 10);
if (bytes > 4096) { uint16_t blocks = 32;
PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes); uint16_t bytes = arg_get_int_def(ctx, 1, 256);
bytes = 4096; bool verbose = arg_get_lit(ctx, 2);
} blocks = bytes / 8;
if (bytes % 8 != 0) { CLIParserFree(ctx);
bytes &= 0xFFF8;
PrintAndLogEx(WARNING, "Number not divided by 8, truncating to %u", bytes);
}
blocks = bytes / 8; if (bytes > 4096) {
cmdp += 2; PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes);
break; bytes = 4096;
case 'v':
verbose = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
} }
//Validations if (bytes % 8 != 0) {
if (errors || bytes == 0) { bytes &= 0xFFF8;
return usage_hf_iclass_eview(); PrintAndLogEx(WARNING, "Number not divided by 8, truncating to %u", bytes);
} }
uint8_t *dump = calloc(bytes, sizeof(uint8_t)); uint8_t *dump = calloc(bytes, sizeof(uint8_t));

View file

@ -1439,10 +1439,10 @@ static int desfire_print_amk_keysetting(uint8_t key_settings, uint8_t num_keys,
break; break;
default: default:
PrintAndLogEx(SUCCESS, PrintAndLogEx(SUCCESS,
" -- Authentication with the specified key is necessary to change any key.\n" " -- Authentication with the specified key is necessary to change any key.\n"
"A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n"
"For keys other then the master or change key, an authentication with the same key is needed." "For keys other then the master or change key, an authentication with the same key is needed."
); );
break; break;
} }
@ -1489,12 +1489,12 @@ static int desfire_print_piccmk_keysetting(uint8_t key_settings, uint8_t num_key
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(INFO, " Key setting: 0x%02X [%c%c%c%c]", PrintAndLogEx(INFO, " Key setting: 0x%02X [%c%c%c%c]",
key_settings, key_settings,
(key_settings & (1 << 3)) ? '1' : '0', (key_settings & (1 << 3)) ? '1' : '0',
(key_settings & (1 << 2)) ? '1' : '0', (key_settings & (1 << 2)) ? '1' : '0',
(key_settings & (1 << 1)) ? '1' : '0', (key_settings & (1 << 1)) ? '1' : '0',
(key_settings & (1 << 0)) ? '1' : '0' (key_settings & (1 << 0)) ? '1' : '0'
); );
PrintAndLogEx(SUCCESS, " [1...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); PrintAndLogEx(SUCCESS, " [1...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)");
PrintAndLogEx(SUCCESS, " [.1..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES"); PrintAndLogEx(SUCCESS, " [.1..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES");
@ -1649,10 +1649,10 @@ static int handler_desfire_select_application(uint8_t *aid) {
int res = send_desfire_cmd(&apdu, !tag->rf_field_on, NULL, &recv_len, &sw, sizeof(dfname_t), true); int res = send_desfire_cmd(&apdu, !tag->rf_field_on, NULL, &recv_len, &sw, sizeof(dfname_t), true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, PrintAndLogEx(WARNING,
_RED_(" Can't select AID 0x%X -> %s"), _RED_(" Can't select AID 0x%X -> %s"),
(aid[2] << 16) + (aid[1] << 8) + aid[0], (aid[2] << 16) + (aid[1] << 8) + aid[0],
GetErrorString(res, &sw) GetErrorString(res, &sw)
); );
DropFieldDesfire(); DropFieldDesfire();
return res; return res;
} }
@ -2430,14 +2430,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
if (usename) if (usename)
PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); PrintAndLogEx(INFO, "DF Name %s", aidhdr.name);
/* /*
uint8_t rootaid[3] = {0x00, 0x00, 0x00}; uint8_t rootaid[3] = {0x00, 0x00, 0x00};
int res = handler_desfire_select_application(rootaid); int res = handler_desfire_select_application(rootaid);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
DropFieldDesfire(); DropFieldDesfire();
return res; return res;
} }
*/ */
int res = handler_desfire_createapp(&aidhdr, usename, usefid); int res = handler_desfire_createapp(&aidhdr, usename, usefid);
DropFieldDesfire(); DropFieldDesfire();

View file

@ -1027,7 +1027,7 @@ static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
} }
// Define prototype to call from within detect. // Define prototype to call from within detect.
static int CmdT55xxWakeUp (const char *Cmd); static int CmdT55xxWakeUp(const char *Cmd);
static int CmdT55xxDetect(const char *Cmd) { static int CmdT55xxDetect(const char *Cmd) {
@ -1054,7 +1054,7 @@ static int CmdT55xxDetect(const char *Cmd) {
return usage_t55xx_detect(); return usage_t55xx_detect();
case 'p': case 'p':
password = param_get32ex(Cmd, cmdp + 1, 0, 16); password = param_get32ex(Cmd, cmdp + 1, 0, 16);
sprintf (wakecmd,"p %08x q",(uint32_t)(password & 0xFFFFFFFF)); sprintf(wakecmd, "p %08x q", (uint32_t)(password & 0xFFFFFFFF));
usepwd = true; usepwd = true;
cmdp += 2; cmdp += 2;
break; break;
@ -1096,11 +1096,11 @@ static int CmdT55xxDetect(const char *Cmd) {
if (usewake) { if (usewake) {
// call wake // call wake
if (try_with_pwd) if (try_with_pwd)
CmdT55xxWakeUp (wakecmd); CmdT55xxWakeUp(wakecmd);
else else
CmdT55xxWakeUp ("q"); CmdT55xxWakeUp("q");
// sleep 90 ms // sleep 90 ms
nanosleep (&sleepperiod, &sleepperiod); nanosleep(&sleepperiod, &sleepperiod);
} }
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false) if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false)
@ -1117,11 +1117,11 @@ static int CmdT55xxDetect(const char *Cmd) {
if (usewake) { if (usewake) {
// call wake // call wake
if (try_with_pwd) if (try_with_pwd)
CmdT55xxWakeUp (wakecmd); CmdT55xxWakeUp(wakecmd);
else else
CmdT55xxWakeUp ("q"); CmdT55xxWakeUp("q");
// sleep 90 ms // sleep 90 ms
nanosleep (&sleepperiod, &sleepperiod); nanosleep(&sleepperiod, &sleepperiod);
} }
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) { if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) {

View file

@ -116,7 +116,7 @@ static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag
if (longyear == false) if (longyear == false)
PrintAndLogEx(NORMAL, "20" NOLF); PrintAndLogEx(NORMAL, "20" NOLF);
PrintAndLogEx(NORMAL, "%s-" NOLF, sprint_hex(tlv->value, startindx) ); PrintAndLogEx(NORMAL, "%s-" NOLF, sprint_hex(tlv->value, startindx));
if (len < startindx + 2) if (len < startindx + 2)
break; break;

View file

@ -462,9 +462,9 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta
if (val & 0x80) { if (val & 0x80) {
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " %s - '%s'", PrintAndLogEx(NORMAL, " %s - '%s'",
bitstrings[bit - 1], bitstrings[bit - 1],
(bits->bit == EMV_BIT(byte, bit)) ? bits->name : "Unknown" (bits->bit == EMV_BIT(byte, bit)) ? bits->name : "Unknown"
); );
} }
if (bits->bit == EMV_BIT(byte, bit)) if (bits->bit == EMV_BIT(byte, bit))
bits ++; bits ++;
@ -535,10 +535,10 @@ static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *ta
static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, int level) { static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, int level) {
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " Date: 20%02lu.%lu.%lu", PrintAndLogEx(NORMAL, " Date: 20%02lu.%lu.%lu",
emv_value_numeric(tlv, 0, 2), emv_value_numeric(tlv, 0, 2),
emv_value_numeric(tlv, 2, 4), emv_value_numeric(tlv, 2, 4),
emv_value_numeric(tlv, 4, 6) emv_value_numeric(tlv, 4, 6)
); );
} }
static uint32_t emv_get_binary(const unsigned char *S) { static uint32_t emv_get_binary(const unsigned char *S) {
@ -749,12 +749,12 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " %02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful", PrintAndLogEx(NORMAL, " %02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful",
tlv->value[i], tlv->value[i],
tlv->value[i + 1], tlv->value[i + 1],
method, method,
condition, condition,
(tlv->value[i] & 0x40) ? "continue" : "fail" (tlv->value[i] & 0x40) ? "continue" : "fail"
); );
} }
} }

View file

@ -227,7 +227,7 @@ void print_buffer(const uint8_t *data, const size_t len, int level) {
hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, mod, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, mod, (sizeof(buf) - strlen(buf) - 1), 0, 1, true);
// add the spaces... // add the spaces...
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3) , " "); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3), " ");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod)); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod));
PrintAndLogEx(INFO, "%s", buf); PrintAndLogEx(INFO, "%s", buf);