mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Merge remote-tracking branch 'upstream/master' into feat/hf-gallagher
This commit is contained in:
commit
de30ba90d1
116 changed files with 3007 additions and 1860 deletions
|
@ -1464,4 +1464,14 @@ B5ADEFCA46C4
|
|||
BF3FE47637EC
|
||||
B290401B0CAD
|
||||
AD11006B0601
|
||||
|
||||
#
|
||||
# Data from Mifare Classic Tool repo
|
||||
# Armenian Metro
|
||||
E4410EF8ED2D
|
||||
6A68A7D83E11
|
||||
0D6057E8133B
|
||||
D3F3B958B8A3
|
||||
3E120568A35C
|
||||
2196FAD8115B
|
||||
7C469FE86855
|
||||
CE99FBC8BD26
|
||||
|
|
|
@ -1052,7 +1052,7 @@ static int CmdAnalyseFoo(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes (strx)"),
|
||||
arg_str1("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -2407,7 +2407,7 @@ static int Cmdbin2hex(const char *Cmd) {
|
|||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("d", "data", "<bin>", "binary string to convert"),
|
||||
arg_str1("d", "data", "<bin>", "binary string to convert"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -167,7 +167,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
|
||||
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
|
||||
arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
|
||||
arg_strx0("f", "file", "<filename>", "file name"),
|
||||
arg_str1("f", "file", "<fn>", "file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -327,7 +327,7 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||
arg_int0("l", "len", "<dec>", "length"),
|
||||
arg_lit0("v", "view", "view dump"),
|
||||
arg_strx0("f", "file", "<filename>", "file name"),
|
||||
arg_str0("f", "file", "<fn>", "save filename"),
|
||||
arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
|
|
@ -196,7 +196,7 @@ static int CmdFlashMemSpiFFSRemove(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "filename", "<fn>", "file to remove"),
|
||||
arg_str1("f", "file", "<fn>", "file to remove"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -743,13 +743,16 @@ int CmdHF14ASim(const char *Cmd) {
|
|||
keypress = kbd_enter_pressed();
|
||||
}
|
||||
|
||||
if (keypress && (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
// inform device to break the sim loop since client has exited
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
}
|
||||
if (keypress) {
|
||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
// inform device to break the sim loop since client has exited
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
}
|
||||
|
||||
if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK))
|
||||
showSectorTable(k_sector, k_sectorsCount);
|
||||
if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
|
||||
showSectorTable(k_sector, k_sectorsCount);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Done");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -2274,7 +2277,7 @@ static int CmdHf14AFindapdu(const char *Cmd) {
|
|||
arg_str0(NULL, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
|
||||
arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
|
||||
arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
|
||||
arg_strx0("s", "skip-ins", "<hex>", "Do not test an instructions (can be specified multiple times)"),
|
||||
arg_strx0("s", "skip-ins", "<hex>", "Do not test an instruction (can be specified multiple times)"),
|
||||
arg_lit0("l", "with-le", "Search for APDUs with Le=0 (case 2S) as well"),
|
||||
arg_lit0("v", "verbose", "Verbose output"),
|
||||
arg_param_end
|
||||
|
|
|
@ -221,7 +221,7 @@ static int CmdHF14BSim(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
|
||||
arg_str1("u", "uid", "hex", "4byte UID/PUPI"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -288,7 +288,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
arg_lit0("r", NULL, "do not read response from card"),
|
||||
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
||||
arg_lit0("v", "verbose", "verbose"),
|
||||
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||
arg_str0("d", "data", "<hex>", "data, bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -1276,7 +1276,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("f", "file", "<filename>", "(optional) filename, if no <name> UID will be used as filename"),
|
||||
arg_str0("f", "file", "<fn>", "(optional) filename, if no <name> UID will be used as filename"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -1822,7 +1822,7 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
|||
" must be 4 bytes: <CLA INS P1 P2>"),
|
||||
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
||||
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
|
||||
arg_strx1("d", "data", "<hex>", "<APDU | data> if `m` parameter included"),
|
||||
arg_str1("d", "data", "<hex>", "<APDU | data> if `m` parameter included"),
|
||||
arg_int0(NULL, "timeout", "<dec>", "timeout in ms"),
|
||||
arg_param_end
|
||||
};
|
||||
|
|
|
@ -1450,7 +1450,7 @@ static int CmdHF15Raw(const char *Cmd) {
|
|||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
arg_lit0("k", NULL, "keep signal field ON after receive"),
|
||||
arg_lit0("r", NULL, "do not read response"),
|
||||
arg_strx1("d", "data", "<hex>", "raw bytes to send"),
|
||||
arg_str1("d", "data", "<hex>", "raw bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -423,7 +423,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "filename of dump"),
|
||||
arg_str1("f", "file", "<fn>", "filename of dump"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -201,7 +201,7 @@ static int emrtd_exchange_commands_noout(sAPDU_t apdu, bool activate_field, bool
|
|||
}
|
||||
|
||||
static char emrtd_calculate_check_digit(char *data) {
|
||||
int mrz_weight[] = {7, 3, 1};
|
||||
const int mrz_weight[] = {7, 3, 1};
|
||||
int value, cd = 0;
|
||||
|
||||
for (int i = 0; i < strlen(data); i++) {
|
||||
|
@ -295,7 +295,7 @@ static void des3_decrypt_cbc(uint8_t *iv, uint8_t *key, uint8_t *input, int inpu
|
|||
}
|
||||
|
||||
static int pad_block(uint8_t *input, int inputlen, uint8_t *output) {
|
||||
uint8_t padding[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t padding[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
memcpy(output, input, inputlen);
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) {
|
|||
|
||||
uint8_t apdu_lengths[5] = {msesa_len, gn_len, map_len, pka_len, ma_len};
|
||||
// pointers to the arrays to be able to iterate
|
||||
uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
|
||||
const uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
|
||||
|
||||
// Proxmark response
|
||||
PacketResponseNG resp;
|
||||
|
|
|
@ -2122,7 +2122,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
|||
arg_u64_0("n", NULL, "<dec>", "number of bits"),
|
||||
arg_lit0("r", NULL, "do not read response"),
|
||||
arg_lit0("s", NULL, "active signal field ON with select"),
|
||||
arg_strx1(NULL, NULL, "<hex>", "raw bytes to send"),
|
||||
arg_str1(NULL, NULL, "<hex>", "raw bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -32,10 +32,11 @@
|
|||
#include "wiegand_formatutils.h"
|
||||
#include "cmdsmartcard.h" // smart select fct
|
||||
#include "proxendian.h"
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
#define NUM_CSNS 9
|
||||
#define ICLASS_KEYS_MAX 8
|
||||
#define ICLASS_AUTH_RETRY 10
|
||||
#define NUM_CSNS 9
|
||||
#define ICLASS_KEYS_MAX 8
|
||||
#define ICLASS_AUTH_RETRY 10
|
||||
#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin"
|
||||
|
||||
static void print_picopass_info(const picopass_hdr_t *hdr);
|
||||
|
@ -165,7 +166,7 @@ static const char *card_types[] = {
|
|||
};
|
||||
|
||||
static uint8_t card_app2_limit[] = {
|
||||
0xff,
|
||||
0x1f,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
|
@ -278,7 +279,8 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
// calc diversified key for selected card
|
||||
HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "failed to read a card, will use default config card data");
|
||||
PrintAndLogEx(FAILED, "failed to read a card");
|
||||
PrintAndLogEx(INFO,"falling back to default config card");
|
||||
}
|
||||
|
||||
// generate dump file
|
||||
|
@ -323,35 +325,47 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
data = p;
|
||||
memset(data, 0xFF, tot_bytes);
|
||||
}
|
||||
|
||||
memset(data + sizeof(picopass_hdr_t), 0xFF, tot_bytes - sizeof(picopass_hdr_t));
|
||||
|
||||
bool old = GetFlushAfterWrite();
|
||||
SetFlushAfterWrite(true);
|
||||
|
||||
// KEYROLL need to encrypt
|
||||
PrintAndLogEx(INFO, "Setting up encryption... " NOLF);
|
||||
uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
if (Encrypt(ffs, ffs) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt FF");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
}
|
||||
|
||||
// local key copy
|
||||
PrintAndLogEx(INFO, "Encrypting local key... " NOLF);
|
||||
uint8_t lkey[8];
|
||||
memcpy(lkey, key, sizeof(lkey));
|
||||
|
||||
uint8_t enckey1[8];
|
||||
if (Encrypt(lkey, enckey1) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt key1");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Copy data... " NOLF);
|
||||
memcpy(data, cc, sizeof(picopass_hdr_t));
|
||||
memcpy(data + (6 * 8), o->data, sizeof(o->data));
|
||||
|
||||
// encrypted keyroll key 0D
|
||||
memcpy(data + (0xD * 8), enckey1, sizeof(enckey1));
|
||||
// encrypted 0xFF
|
||||
for (uint8_t i = 0xe; i < 0x14; i++) {
|
||||
for (uint8_t i = 0xD; i < 0x14; i++) {
|
||||
memcpy(data + (i * 8), ffs, sizeof(ffs));
|
||||
}
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// encrypted partial keyroll key 14
|
||||
PrintAndLogEx(INFO, "Setting encrypted partial key14... " NOLF);
|
||||
uint8_t foo[8] = {0x15};
|
||||
memcpy(foo + 1, lkey, 7);
|
||||
uint8_t enckey2[8];
|
||||
|
@ -359,34 +373,43 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
PrintAndLogEx(WARNING, "failed to encrypt partial 1");
|
||||
}
|
||||
memcpy(data + (0x14 * 8), enckey2, sizeof(enckey2));
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
|
||||
// encrypted partial keyroll key 15
|
||||
PrintAndLogEx(INFO, "Setting encrypted partial key15... " NOLF);
|
||||
memset(foo, 0xFF, sizeof(foo));
|
||||
foo[0] = lkey[7];
|
||||
if (Encrypt(foo, enckey2) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt partial 2");
|
||||
}
|
||||
memcpy(data + (0x15 * 8), enckey2, sizeof(enckey2));
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// encrypted 0xFF
|
||||
PrintAndLogEx(INFO, "Setting 0xFF's... " NOLF);
|
||||
for (uint8_t i = 0x16; i <= app1_limit; i++) {
|
||||
memcpy(data + (i * 8), ffs, sizeof(ffs));
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// revert potential modified app1_limit
|
||||
cc->conf.app_limit = old_limit;
|
||||
|
||||
SetFlushAfterWrite(old);
|
||||
} else {
|
||||
memcpy(data, cc, sizeof(picopass_hdr_t));
|
||||
memcpy(data + (6 * 8), o->data, sizeof(o->data));
|
||||
}
|
||||
|
||||
//Send to device
|
||||
PrintAndLogEx(INFO, "Uploading to device... ");
|
||||
uint16_t bytes_sent = 0;
|
||||
iclass_upload_emul(data, tot_bytes, &bytes_sent);
|
||||
free(data);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "sent %u bytes of data to device emulator memory", bytes_sent);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%u") " bytes of data to device emulator memory", bytes_sent);
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass eview") "` to view dump file");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass sim -t 3") "` to start simulating config card");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -454,15 +477,21 @@ static void fuse_config(const picopass_hdr_t *hdr) {
|
|||
PrintAndLogEx(SUCCESS, " RA........... Read access enabled (non-secure mode)");
|
||||
else
|
||||
PrintAndLogEx(INFO, " RA........... Read access not enabled");
|
||||
|
||||
if (notset(fuses, FUSE_FPROD0) && isset(fuses, FUSE_FPROD1)) {
|
||||
PrintAndLogEx(INFO, " PROD0/1...... Default production fuses");
|
||||
}
|
||||
}
|
||||
|
||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) {
|
||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb, uint8_t *books, uint8_t *pages) {
|
||||
// How to determine chip type
|
||||
|
||||
// mem-bit 7 = 16K
|
||||
// mem-bit 5 = Book
|
||||
// mem-bit 4 = 2K
|
||||
// chip-bit 4 = Multi App
|
||||
*books = 1;
|
||||
*pages = 1;
|
||||
|
||||
uint8_t k16 = isset(mem_cfg, 0x80);
|
||||
//uint8_t k2 = isset(mem_cfg, 0x10);
|
||||
|
@ -477,12 +506,16 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas,
|
|||
} else if (notset(chip_cfg, 0x10) && !k16 && !book) {
|
||||
*kb = 16;
|
||||
*app_areas = 16;
|
||||
*pages = 8;
|
||||
} else if (isset(chip_cfg, 0x10) && k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 3;
|
||||
*books = 2;
|
||||
} else if (notset(chip_cfg, 0x10) && !k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 17;
|
||||
*pages = 8;
|
||||
*books = 2;
|
||||
} else {
|
||||
*kb = 32;
|
||||
*app_areas = 2;
|
||||
|
@ -506,8 +539,10 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
|
|||
uint8_t chip = hdr->conf.chip_config;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
uint8_t books = 1;
|
||||
uint8_t pages = 1;
|
||||
|
||||
getMemConfig(mem, chip, &app_areas, &kb, &books, &pages);
|
||||
|
||||
uint8_t type = get_mem_config(hdr);
|
||||
uint8_t app1_limit = hdr->conf.app_limit - 5; // minus header blocks
|
||||
|
@ -522,9 +557,26 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
|
|||
return;
|
||||
}
|
||||
|
||||
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, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )"
|
||||
, kb
|
||||
, app_areas
|
||||
, ((app2_limit + 1) * 8) * books * pages);
|
||||
|
||||
PrintAndLogEx(INFO, " %u books / %u pages"
|
||||
, books
|
||||
, pages
|
||||
);
|
||||
PrintAndLogEx(INFO, " First book / first page configuration");
|
||||
PrintAndLogEx(INFO, " Config | 0 - 5 ( 0x00 - 0x05 ) - 6 blocks ");
|
||||
PrintAndLogEx(INFO, " AA1 | 6 - %2d ( 0x06 - 0x%02X ) - %u blocks", app1_limit + 5, app1_limit + 5, app1_limit);
|
||||
if (app1_limit + 5 < app2_limit ) {
|
||||
PrintAndLogEx(INFO, " AA2 | %2d - %2d ( 0x%02X - 0x%02X ) - %u blocks", app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit, app2_limit - app1_limit);
|
||||
}
|
||||
/*
|
||||
[=] 32 KBits/3 App Areas ( 2048 bytes )
|
||||
[=] AA1 blocks 250 { 0x06 - 0xFF (06 - 255) }
|
||||
[=] AA2 blocks 5 { 0x100 - 0xFF (256 - 255) }
|
||||
*/
|
||||
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("KeyAccess") " ------------------------");
|
||||
PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *");
|
||||
|
@ -557,8 +609,19 @@ void print_picopass_header(const picopass_hdr_t *hdr) {
|
|||
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)));
|
||||
|
||||
if (memcmp(hdr->key_d, zeros, sizeof(zeros)) && memcmp(hdr->key_d, empty, sizeof(empty))) {
|
||||
PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
}
|
||||
|
||||
if (memcmp(hdr->key_c, zeros, sizeof(zeros)) && memcmp(hdr->key_c, empty, sizeof(empty))) {
|
||||
PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
} else {
|
||||
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)));
|
||||
}
|
||||
|
||||
|
@ -834,25 +897,28 @@ static int CmdHFiClassInfo(const char *Cmd) {
|
|||
|
||||
int read_iclass_csn(bool loop, bool verbose) {
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
do {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xff;
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000)) {
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
if (loop) {
|
||||
if (status == 0xFF) {
|
||||
if (resp.status == PM3_ERFTRANS) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (status == 0 || status == 0xFF) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "iCLASS / ISO15693 card select failed");
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "iCLASS / Picopass card select failed ( %d )", r->status);
|
||||
res = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
|
@ -860,13 +926,17 @@ int read_iclass_csn(bool loop, bool verbose) {
|
|||
|
||||
picopass_hdr_t *card = calloc(1, sizeof(picopass_hdr_t));
|
||||
if (card) {
|
||||
memcpy(card, (picopass_hdr_t *)resp.data.asBytes, sizeof(picopass_hdr_t));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
memcpy(card, &r->header.hdr, sizeof(picopass_hdr_t));
|
||||
if (loop == false) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
|
||||
iclass_set_last_known_card(card);
|
||||
free(card);
|
||||
res = PM3_SUCCESS;
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
res = PM3_EMALLOC;
|
||||
}
|
||||
}
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
|
@ -1240,7 +1310,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
} else {
|
||||
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data)));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "encrypted... %s", sprint_hex_inrow(enc_data, sizeof(enc_data)));
|
||||
PrintAndLogEx(SUCCESS, "plain....... " _YELLOW_("%s"), sprint_hex_inrow(dec_data, sizeof(dec_data)));
|
||||
|
||||
if (use_sc && use_decode6)
|
||||
DecodeBlock6(dec_data);
|
||||
|
@ -1256,7 +1328,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
uint8_t applimit = hdr->conf.app_limit;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
uint8_t books = 1;
|
||||
uint8_t pages = 1;
|
||||
getMemConfig(mem, chip, &app_areas, &kb, &books, &pages);
|
||||
|
||||
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
|
||||
|
||||
|
@ -1455,39 +1529,45 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(SUCCESS, "plain....... %s", sprint_hex_inrow(blk_data, sizeof(blk_data)));
|
||||
|
||||
if (use_sc) {
|
||||
Encrypt(blk_data, blk_data);
|
||||
} else {
|
||||
iclass_encrypt_block_data(blk_data, key);
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "encrypted block %s", sprint_hex(blk_data, 8));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "encrypted... " _YELLOW_("%s"), sprint_hex_inrow(blk_data, sizeof(blk_data)));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) {
|
||||
|
||||
uint8_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xff;
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
|
||||
// no tag found or button pressed
|
||||
if ((isok == 0) || isok == 0xFF) {
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", isok);
|
||||
PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", r->status);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
|
||||
if (CSN != NULL)
|
||||
memcpy(CSN, hdr->csn, 8);
|
||||
|
||||
|
@ -1614,34 +1694,41 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
|
||||
uint8_t app_limit1 = 0, app_limit2 = 0;
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
|
||||
//get CSN and config
|
||||
PacketResponseNG resp;
|
||||
uint8_t tag_data[0x100 * 8];
|
||||
memset(tag_data, 0xFF, sizeof(tag_data));
|
||||
|
||||
|
||||
iclass_card_select_t payload_rdr = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload_rdr, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
|
||||
if (readStatus == 0) {
|
||||
if (resp.status == PM3_ERFTRANS) {
|
||||
PrintAndLogEx(FAILED, "no tag found");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
if (r->status == FLAG_ICLASS_NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
|
||||
if (readStatus & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
|
||||
if (r->status & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
|
||||
|
||||
memcpy(tag_data, hdr, 24);
|
||||
|
||||
|
@ -1661,11 +1748,6 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
app_limit1 = hdr->conf.app_limit;
|
||||
app_limit2 = card_app2_limit[type];
|
||||
}
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
|
@ -2470,11 +2552,10 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
|||
);
|
||||
*/
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
|
||||
|
||||
|
||||
int i = startblock;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Tag memory") " ---------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, " block# | data | ascii |lck| info");
|
||||
PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------");
|
||||
|
@ -2484,7 +2565,7 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
|||
);
|
||||
|
||||
if (i != 1)
|
||||
PrintAndLogEx(INFO, "....");
|
||||
PrintAndLogEx(INFO, " ......");
|
||||
|
||||
while (i <= endblock) {
|
||||
uint8_t *blk = iclass_dump + (i * 8);
|
||||
|
@ -3956,88 +4037,101 @@ int CmdHFiClass(const char *Cmd) {
|
|||
|
||||
int info_iclass(void) {
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||
|
||||
// no tag found or button pressed
|
||||
if (readStatus == 0 || readStatus == 0xFF) {
|
||||
DropField();
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)resp.data.asBytes;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------");
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CSN) {
|
||||
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||
}
|
||||
|
||||
// page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks.
|
||||
// page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area)));
|
||||
} else {
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CC) {
|
||||
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)));
|
||||
|
||||
if (readStatus & FLAG_ICLASS_AIA) {
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||
}
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
print_picopass_info(hdr);
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
|
||||
|
||||
uint8_t aia[8];
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia));
|
||||
} else {
|
||||
memcpy(aia, hdr->app_issuer_area, sizeof(aia));
|
||||
}
|
||||
|
||||
// if CSN ends with FF12E0, it's inside HID CSN range.
|
||||
bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0);
|
||||
|
||||
bool legacy = (memcmp(aia, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0);
|
||||
bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
|
||||
|
||||
if (isHidRange) {
|
||||
PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("HID range"));
|
||||
if (legacy)
|
||||
PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS legacy"));
|
||||
if (se_enabled)
|
||||
PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE"));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range"));
|
||||
}
|
||||
|
||||
uint8_t cardtype = get_mem_config(hdr);
|
||||
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
|
||||
// no tag found or button pressed
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
picopass_ns_hdr_t *ns_hdr = &r->header.ns_hdr;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------");
|
||||
|
||||
if ((r->status & FLAG_ICLASS_CSN) == FLAG_ICLASS_CSN) {
|
||||
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||
}
|
||||
|
||||
if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) {
|
||||
PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||
}
|
||||
|
||||
// page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks.
|
||||
// page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area)));
|
||||
} else {
|
||||
|
||||
if ((r->status & FLAG_ICLASS_CC) == FLAG_ICLASS_CC) {
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
}
|
||||
|
||||
if (memcmp(hdr->key_d, zeros, sizeof(zeros))) {
|
||||
PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
}
|
||||
|
||||
if (memcmp(hdr->key_c, zeros, sizeof(zeros))) {
|
||||
PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s credit key ( hidden )", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
}
|
||||
|
||||
|
||||
if ((r->status & FLAG_ICLASS_AIA) == FLAG_ICLASS_AIA) {
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||
}
|
||||
}
|
||||
|
||||
if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) {
|
||||
print_picopass_info(hdr);
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
|
||||
|
||||
uint8_t aia[8];
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia));
|
||||
} else {
|
||||
memcpy(aia, hdr->app_issuer_area, sizeof(aia));
|
||||
}
|
||||
|
||||
// if CSN ends with FF12E0, it's inside HID CSN range.
|
||||
bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0);
|
||||
|
||||
bool legacy = (memcmp(aia, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0);
|
||||
bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
|
||||
|
||||
if (isHidRange) {
|
||||
PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("HID range"));
|
||||
if (legacy)
|
||||
PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS legacy"));
|
||||
if (se_enabled)
|
||||
PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE"));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range"));
|
||||
}
|
||||
|
||||
uint8_t cardtype = get_mem_config(hdr);
|
||||
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,21 +13,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "fileutils.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
typedef struct iclass_block {
|
||||
uint8_t d[8];
|
||||
} iclass_block_t;
|
||||
|
||||
typedef struct iclass_prekey {
|
||||
uint8_t mac[4];
|
||||
uint8_t key[8];
|
||||
} iclass_prekey_t;
|
||||
|
||||
typedef struct {
|
||||
char desc[70];
|
||||
uint8_t data[16];
|
||||
} iclass_config_card_item_t;
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ static int jooki_encode(uint8_t *iv, uint8_t tid, uint8_t fid, uint8_t *uid, uin
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1], iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
|
||||
const uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1], iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
|
||||
uint8_t enc[JOOKI_PLAIN_LEN] = {0};
|
||||
for (uint8_t i = 0; i < JOOKI_PLAIN_LEN; i++) {
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ static int CmdHFKSX6924Info(const char *Cmd) {
|
|||
uint16_t sw = 0;
|
||||
int res = KSX6924Select(true, true, buf, sizeof(buf), &len, &sw);
|
||||
|
||||
if (res) {
|
||||
if (res || (len == 0)) {
|
||||
if (keep == false) {
|
||||
DropField();
|
||||
}
|
||||
|
@ -134,6 +134,7 @@ static int CmdHFKSX6924Info(const char *Cmd) {
|
|||
// FCI Response is a BER-TLV, we are interested in tag 6F,B0 only.
|
||||
const uint8_t *p = buf;
|
||||
struct tlv fci_tag;
|
||||
memset(&fci_tag, 0, sizeof(fci_tag));
|
||||
|
||||
while (len > 0) {
|
||||
memset(&fci_tag, 0, sizeof(fci_tag));
|
||||
|
@ -244,7 +245,7 @@ static int CmdHFKSX6924Initialize(const char *Cmd) {
|
|||
arg_param_begin,
|
||||
arg_lit0("k", "keep", "keep field ON for next command"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_strx1(NULL, NULL, "<mpda 4byte hex>", NULL),
|
||||
arg_str1(NULL, NULL, "<mpda 4byte hex>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -297,7 +298,7 @@ static int CmdHFKSX6924PRec(const char *Cmd) {
|
|||
arg_param_begin,
|
||||
arg_lit0("k", "keep", "keep field ON for next command"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_strx1(NULL, NULL, "<record 1byte HEX>", NULL),
|
||||
arg_str1(NULL, NULL, "<record 1byte HEX>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -762,7 +762,7 @@ static int CmdLegicDump(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "specify a filename for dump file"),
|
||||
arg_str0("f", "file", "<fn>", "Dump filename"),
|
||||
arg_lit0(NULL, "de", "deobfuscate dump data (xor with MCC)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -859,7 +859,7 @@ static int CmdLegicRestore(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "specify a filename to restore"),
|
||||
arg_str1("f", "file", "<fn>", "Filename to restore"),
|
||||
arg_lit0(NULL, "ob", "obfuscate dump data (xor with MCC)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -963,7 +963,7 @@ static int CmdLegicELoad(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "Specify a filename to restore"),
|
||||
arg_str1("f", "file", "<fn>", "Filename to restore"),
|
||||
arg_int0("t", "type", "<dec>", "Tag type to simulate."),
|
||||
arg_lit0(NULL, "obfuscate", "Obfuscate dump data (xor with MCC)"),
|
||||
arg_param_end
|
||||
|
@ -1032,7 +1032,7 @@ static int CmdLegicESave(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "Specify a filename to save"),
|
||||
arg_str0("f", "file", "<fn>", "Filename to save"),
|
||||
arg_int0("t", "type", "<dec>", "Tag type"),
|
||||
arg_lit0(NULL, "deobfuscate", "De-obfuscate dump data (xor with MCC)"),
|
||||
arg_param_end
|
||||
|
|
|
@ -729,7 +729,7 @@ static int CmdHfLTRestore(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "specify a filename for dumpfile"),
|
||||
arg_str1("f", "file", "<fn>", "specify a filename for dumpfile"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -444,7 +444,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "hf mf rdbl",
|
||||
"Read MIFARE Classic block",
|
||||
"hf mf rdbl --blk 0 -k FFFFFFFFFFFF\n"
|
||||
"hf mf rdbl -b 3 -v -> get block 3, decode sector trailer\n"
|
||||
"hf mf rdbl --blk 3 -v -> get block 3, decode sector trailer\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -6133,11 +6133,11 @@ static int CmdHF14AMfView(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14AGen3View(const char *Cmd) {
|
||||
static int CmdHF14AGen4View(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf gview",
|
||||
"View `magic gen3 gtu` card memory",
|
||||
"View `magic gen4 gtu` card memory",
|
||||
"hf mf gview\n"
|
||||
"hf mf gview --4k"
|
||||
);
|
||||
|
@ -6147,6 +6147,7 @@ static int CmdHF14AGen3View(const char *Cmd) {
|
|||
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
|
||||
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
|
||||
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
|
||||
arg_str0("p", "pwd", "<hex>", "password 4bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -6154,9 +6155,18 @@ static int CmdHF14AGen3View(const char *Cmd) {
|
|||
bool m1 = arg_get_lit(ctx, 2);
|
||||
bool m2 = arg_get_lit(ctx, 3);
|
||||
bool m4 = arg_get_lit(ctx, 4);
|
||||
|
||||
int pwd_len = 0;
|
||||
uint8_t pwd[4] = {0};
|
||||
CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// validations
|
||||
if (pwd_len != 4 && pwd_len != 0) {
|
||||
PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if ((m0 + m1 + m2 + m4) > 1) {
|
||||
PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
|
||||
return PM3_EINVARG;
|
||||
|
@ -6183,7 +6193,7 @@ static int CmdHF14AGen3View(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "View magic gen3 GTU MIFARE Classic " _GREEN_("%s"), s);
|
||||
PrintAndLogEx(SUCCESS, "View magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s);
|
||||
PrintAndLogEx(INFO, "." NOLF);
|
||||
|
||||
// Select card to get UID/UIDLEN information
|
||||
|
@ -6221,7 +6231,7 @@ static int CmdHF14AGen3View(const char *Cmd) {
|
|||
|
||||
for (uint16_t i = 0; i < block_cnt; i++) {
|
||||
|
||||
if (mfG3GetBlock(i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) {
|
||||
if (mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Can't get magic card block: %u", i);
|
||||
PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
|
||||
free(dump);
|
||||
|
@ -6290,8 +6300,8 @@ static command_t CommandTable[] = {
|
|||
{"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"},
|
||||
{"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"},
|
||||
{"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3 GTU") " -----------------------"},
|
||||
{"gview", CmdHF14AGen3View, IfPm3Iso14443a, "View card"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"},
|
||||
{"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"},
|
||||
// {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"},
|
||||
// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
|
|
|
@ -1056,7 +1056,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0(NULL, "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
|
||||
arg_str0(NULL, "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
|
||||
arg_str0("k", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_str0("d", "dict", "<file>", "File with keys dictionary"),
|
||||
arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
|
||||
|
@ -1914,8 +1914,8 @@ static int CmdHF14ADesBruteApps(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("s", "start", "<hex>", "Starting App ID as hex bytes (3 bytes, big endian)"),
|
||||
arg_strx0("e", "end", "<hex>", "Last App ID as hex bytes (3 bytes, big endian)"),
|
||||
arg_str0("s", "start", "<hex>", "Starting App ID as hex bytes (3 bytes, big endian)"),
|
||||
arg_str0("e", "end", "<hex>", "Last App ID as hex bytes (3 bytes, big endian)"),
|
||||
arg_int0("i", "step", "<dec>", "Increment step when bruteforcing"),
|
||||
arg_lit0("m", "mad", "Only bruteforce the MAD range"),
|
||||
arg_param_end
|
||||
|
|
|
@ -456,7 +456,7 @@ static int CmdHFMFPWritePerso(const char *Cmd) {
|
|||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_str1(NULL, "ki", "<hex>", " key number, 2 hex bytes"),
|
||||
arg_strx0(NULL, "key", "<hex>", " key, 16 hex bytes"),
|
||||
arg_str0(NULL, "key", "<hex>", " key, 16 hex bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -521,7 +521,7 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
|
|||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("v", "verbose", 0, 2, "show internal data."),
|
||||
arg_strx0("k", "key", "<hex>", "key, 16 hex bytes"),
|
||||
arg_str0("k", "key", "<hex>", "key, 16 hex bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -1772,6 +1772,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
arg_lit0("l", NULL, "swap entered key's endianness"),
|
||||
arg_int1("b", "block", "<dec>", "block number to write"),
|
||||
arg_str1("d", "data", "<hex>", "block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"),
|
||||
arg_lit0(NULL, "force", "force operation even if address is out of range"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -1786,6 +1787,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
int datalen = 0;
|
||||
uint8_t data[16] = {0x00};
|
||||
CLIGetHexWithReturn(ctx, 4, data, &datalen);
|
||||
bool force = arg_get_lit(ctx, 5);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
bool has_auth_key = false;
|
||||
|
@ -1823,7 +1825,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (blockno > maxblockno) {
|
||||
if ((blockno > maxblockno) && (!force)) {
|
||||
PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
@ -1901,6 +1903,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) {
|
|||
arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
|
||||
arg_lit0("l", NULL, "swap entered key's endianness"),
|
||||
arg_int1("b", "block", "<dec>", "block number to read"),
|
||||
arg_lit0(NULL, "force", "force operation even if address is out of range"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -1910,6 +1913,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) {
|
|||
CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
|
||||
bool swap_endian = arg_get_lit(ctx, 2);
|
||||
int blockno = arg_get_int_def(ctx, 3, -1);
|
||||
bool force = arg_get_lit(ctx, 4);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
bool has_auth_key = false;
|
||||
|
@ -1942,7 +1946,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (blockno > maxblockno) {
|
||||
if ((blockno > maxblockno) && (!force)) {
|
||||
PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ static void dither_chan_inplace(int16_t *chan, uint16_t width, uint16_t height)
|
|||
int16_t newp = oldp > 127 ? 255 : 0;
|
||||
chan[X + Y * width] = newp;
|
||||
int16_t err = oldp - newp;
|
||||
float m[] = {7, 3, 5, 1};
|
||||
const float m[] = {7, 3, 5, 1};
|
||||
if (X < width - 1) {
|
||||
chan[X + 1 + Y * width] = chan[X + 1 + Y * width] + m[0] / 16 * err;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ static void dither_rgb_inplace(int16_t *chanR, int16_t *chanG, int16_t *chanB, u
|
|||
int16_t errR = oldR - newR;
|
||||
int16_t errG = oldG - newG;
|
||||
int16_t errB = oldB - newB;
|
||||
float m[] = {7, 3, 5, 1};
|
||||
const float m[] = {7, 3, 5, 1};
|
||||
if (Y % 2) {
|
||||
if (XX > 0) {
|
||||
chanR[XX - 1 + Y * width] = (chanR[XX - 1 + Y * width] + m[0] / 16 * errR);
|
||||
|
@ -593,7 +593,7 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red)
|
|||
uint8_t step_4[2] = {0xcd, 0x04};
|
||||
uint8_t step_6[2] = {0xcd, 0x06};
|
||||
uint8_t rx[20] = {0};
|
||||
uint16_t actrxlen[20], i = 0, progress = 0;
|
||||
uint16_t actrxlen[20], i, progress;
|
||||
|
||||
if (model_nr == M1in54B) {
|
||||
step_5[2] = 100;
|
||||
|
@ -616,6 +616,7 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red)
|
|||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PrintAndLogEx(DEBUG, "1.54_Step7: e-paper config2 (red)");
|
||||
if (model_nr == M1in54B) { //1.54inch B Keychain
|
||||
for (i = 0; i < 50; i++) {
|
||||
|
@ -635,12 +636,13 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red)
|
|||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PrintAndLogEx(DEBUG, "1.54_Step9");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
||||
uint8_t progress = 0;
|
||||
uint8_t progress;
|
||||
uint8_t step0[2] = {0xcd, 0x0d};
|
||||
uint8_t step1[3] = {0xcd, 0x00, 10}; // select e-paper type and reset e-paper
|
||||
// 4 :2.13inch e-Paper
|
||||
|
@ -667,14 +669,12 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
// uint8_t step13[2]={0xcd,0x0b}; // Judge whether the power supply is turned off successfully
|
||||
// uint8_t step14[2]={0xcd,0x0c}; // The end of the transmission
|
||||
uint8_t rx[20];
|
||||
uint16_t actrxlen[20], i = 0;
|
||||
|
||||
|
||||
uint16_t actrxlen[20], i;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(ERR, "No tag found");
|
||||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
|
@ -711,40 +711,41 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "model_nr = %d", model_nr);
|
||||
int ret;
|
||||
|
||||
PrintAndLogEx(DEBUG, "Step0");
|
||||
ret = transceive_blocking(step0, 2, rx, 20, actrxlen, true); //cd 0d
|
||||
int ret = transceive_blocking(step0, 2, rx, 20, actrxlen, true); //cd 0d
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PrintAndLogEx(DEBUG, "Step1: e-paper config");
|
||||
//step1[2] screen model
|
||||
//step8[2] nr of bytes sent at once
|
||||
//step13[2] nr of bytes sent for the second time
|
||||
// step1[2] screen model
|
||||
// step8[2] nr of bytes sent at once
|
||||
// step13[2] nr of bytes sent for the second time
|
||||
// generally, step8 sends a black image, step13 sends a red image
|
||||
if (model_nr == M2in13) { //2.13inch
|
||||
if (model_nr == M2in13) { // 2.13inch
|
||||
step1[2] = EPD_2IN13V2;
|
||||
step8[2] = 16;
|
||||
step13[2] = 0;
|
||||
} else if (model_nr == M2in9) { //2.9inch
|
||||
} else if (model_nr == M2in9) { // 2.9inch
|
||||
step1[2] = EPD_2IN9;
|
||||
step8[2] = 16;
|
||||
step13[2] = 0;
|
||||
} else if (model_nr == M4in2) { //4.2inch
|
||||
} else if (model_nr == M4in2) { // 4.2inch
|
||||
step1[2] = EPD_4IN2;
|
||||
step8[2] = 100;
|
||||
step13[2] = 0;
|
||||
} else if (model_nr == M7in5) { //7.5inch
|
||||
} else if (model_nr == M7in5) { // 7.5inch
|
||||
step1[2] = EPD_7IN5V2;
|
||||
step8[2] = 120;
|
||||
step13[2] = 0;
|
||||
} else if (model_nr == M2in7) { //2.7inch
|
||||
} else if (model_nr == M2in7) { // 2.7inch
|
||||
step1[2] = EPD_2IN7;
|
||||
step8[2] = 121;
|
||||
// Send blank data for the first time, and send other data to 0xff without processing the bottom layer
|
||||
step13[2] = 121;
|
||||
//Sending the second data is the real image data. If the previous 0xff is not sent, the last output image is abnormally black
|
||||
} else if (model_nr == M2in13B) { //2.13inch B
|
||||
// Sending the second data is the real image data. If the previous 0xff is not sent, the last output image is abnormally black
|
||||
} else if (model_nr == M2in13B) { // 2.13inch B
|
||||
step1[2] = EPD_2IN13BC;
|
||||
step8[2] = 106;
|
||||
step13[2] = 106;
|
||||
|
@ -755,31 +756,35 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
}
|
||||
|
||||
if (model_nr == M1in54B) {
|
||||
ret = transceive_blocking(step1, 2, rx, 20, actrxlen, true); //cd 00
|
||||
ret = transceive_blocking(step1, 2, rx, 20, actrxlen, true); // cd 00
|
||||
} else {
|
||||
ret = transceive_blocking(step1, 3, rx, 20, actrxlen, true);
|
||||
}
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
PrintAndLogEx(DEBUG, "Step2: e-paper normal mode type");
|
||||
ret = transceive_blocking(step2, 2, rx, 20, actrxlen, true); //cd 01
|
||||
ret = transceive_blocking(step2, 2, rx, 20, actrxlen, true); // cd 01
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
PrintAndLogEx(DEBUG, "Step3: e-paper config1");
|
||||
ret = transceive_blocking(step3, 2, rx, 20, actrxlen, true); //cd 02
|
||||
ret = transceive_blocking(step3, 2, rx, 20, actrxlen, true); // cd 02
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(200);
|
||||
PrintAndLogEx(DEBUG, "Step4: e-paper power on");
|
||||
ret = transceive_blocking(step4, 2, rx, 20, actrxlen, true); //cd 03
|
||||
ret = transceive_blocking(step4, 2, rx, 20, actrxlen, true); // cd 03
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (model_nr == M1in54B) {
|
||||
// 1.54B Keychain handler
|
||||
PrintAndLogEx(DEBUG, "Start_Drawing_1in54B");
|
||||
|
@ -787,27 +792,27 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
//1.54B Data transfer is complete and wait for refresh
|
||||
// 1.54B Data transfer is complete and wait for refresh
|
||||
} else {
|
||||
PrintAndLogEx(DEBUG, "Step5: e-paper config2");
|
||||
ret = transceive_blocking(step5, 2, rx, 20, actrxlen, true); //cd 05
|
||||
ret = transceive_blocking(step5, 2, rx, 20, actrxlen, true); // cd 05
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
msleep(100);
|
||||
PrintAndLogEx(DEBUG, "Step6: EDP load to main") ;
|
||||
ret = transceive_blocking(step6, 2, rx, 20, actrxlen, true); //cd 06
|
||||
ret = transceive_blocking(step6, 2, rx, 20, actrxlen, true); // cd 06
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
msleep(100);
|
||||
PrintAndLogEx(DEBUG, "Step7: Data preparation");
|
||||
ret = transceive_blocking(step7, 2, rx, 20, actrxlen, true); //cd 07
|
||||
ret = transceive_blocking(step7, 2, rx, 20, actrxlen, true); // cd 07
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "Step8: Start data transfer");
|
||||
if (model_nr == M2in13) { //2.13inch
|
||||
if (model_nr == M2in13) { // 2.13inch
|
||||
for (i = 0; i < 250; i++) {
|
||||
read_black(i, step8, model_nr, black);
|
||||
ret = transceive_blocking(step8, 19, rx, 20, actrxlen, true); // cd 08
|
||||
|
@ -939,6 +944,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
|
|||
} else if (model_nr == M7in5HD) {
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
uint8_t fail_num = 0;
|
||||
while (1) {
|
||||
if (model_nr == M1in54B) {
|
||||
|
@ -1006,7 +1012,7 @@ static int CmdHF14AWSLoadBmp(const char *Cmd) {
|
|||
arg_param_begin,
|
||||
arg_int1("m", NULL, "<nr>", modeldesc),
|
||||
arg_lit0("s", "save", "save dithered version in filename-[n].bmp, only for RGB BMP"),
|
||||
arg_str1("f", "file", "<filename>", "filename[.bmp] to upload to tag"),
|
||||
arg_str1("f", "file", "<fn>", "specify filename[.bmp] to upload to tag"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ static int CmdDestronClone(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx1("u", "uid", "<hex>", "5 bytes max"),
|
||||
arg_str1("u", "uid", "<hex>", "5 bytes max"),
|
||||
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
||||
arg_param_end
|
||||
|
|
|
@ -200,7 +200,7 @@ int CmdEM4x50ELoad(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "filename", "<fn>", "dump filename (bin/eml/json)"),
|
||||
arg_str1("f", "file", "<fn>", "dump filename (bin/eml/json)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -237,7 +237,7 @@ int CmdEM4x50ESave(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "save filename"),
|
||||
arg_str0("f", "file", "<fn>", "specifiy filename"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -441,7 +441,7 @@ int CmdEM4x50Chk(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "dictionary filename"),
|
||||
arg_str0("f", "file", "<fn>", "specify dictionary filename"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -749,7 +749,7 @@ int CmdEM4x50Dump(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "dump filename (bin/eml/json)"),
|
||||
arg_str0("f", "file", "<fn>", "specify dump filename (bin/eml/json)"),
|
||||
arg_str0("p", "pwd", "<hex>", "password, 4 hex bytes, lsb"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -1060,7 +1060,7 @@ int CmdEM4x50Restore(const char *Cmd) {
|
|||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("u", "uid", "<hex>", "uid, 4 hex bytes, msb"),
|
||||
arg_str0("f", "file", "<fn>", "dump filename (bin/eml/json)"),
|
||||
arg_str0("f", "file", "<fn>", "specify dump filename (bin/eml/json)"),
|
||||
arg_str0("p", "pwd", "<hex>", "password, 4 hex bytes, lsb"),
|
||||
arg_param_end
|
||||
};
|
||||
|
|
|
@ -27,6 +27,64 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int demod_guard_raw(uint8_t *raw, uint8_t rlen) {
|
||||
|
||||
if (rlen != 12) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t bits[96] = {0x00};
|
||||
bytes_to_bytebits(raw, rlen, bits);
|
||||
|
||||
// start after 6 bit preamble
|
||||
size_t start_idx = 6;
|
||||
uint8_t bits_no_spacer[90];
|
||||
memcpy(bits_no_spacer, bits + start_idx, 90);
|
||||
|
||||
// remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
|
||||
size_t len = removeParity(bits_no_spacer, 0, 5, 3, 90); // source, startloc, paritylen, ptype, length_to_run
|
||||
if (len != 72) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII spacer removal did not produce 72 bits: %zu, start: %zu", len, start_idx);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t plain[8] = {0x00};
|
||||
|
||||
// get key and then get all 8 bytes of payload decoded
|
||||
uint8_t xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
|
||||
for (size_t idx = 0; idx < 8; idx++) {
|
||||
plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey;
|
||||
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]);
|
||||
}
|
||||
|
||||
// plain contains 8 Bytes (64 bits) of decrypted raw tag data
|
||||
uint8_t fmtlen = plain[0] >> 2;
|
||||
uint32_t FC = 0;
|
||||
uint32_t Card = 0;
|
||||
|
||||
bool unknown = false;
|
||||
switch (fmtlen) {
|
||||
case 36:
|
||||
FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1);
|
||||
Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5);
|
||||
break;
|
||||
case 26:
|
||||
FC = ((plain[3] & 0x7F) << 1) | (plain[4] >> 7);
|
||||
Card = ((plain[4] & 0x7F) << 9) | (plain[5] << 1) | (plain[6] >> 7);
|
||||
break;
|
||||
default :
|
||||
unknown = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unknown)
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %s", fmtlen, sprint_hex_inrow(raw, rlen));
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %s", fmtlen, FC, Card, sprint_hex_inrow(raw, rlen));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// attempts to demodulate and identify a G_Prox_II verex/chubb card
|
||||
// WARNING: if it fails during some points it will destroy the g_DemodBuffer data
|
||||
// but will leave the g_GraphBuffer intact.
|
||||
|
@ -59,7 +117,6 @@ int demodGuard(bool verbose) {
|
|||
}
|
||||
|
||||
// got a good demod of 96 bits
|
||||
|
||||
uint8_t plain[8] = {0x00};
|
||||
uint8_t xorKey = 0;
|
||||
size_t startIdx = preambleIndex + 6; //start after 6 bit preamble
|
||||
|
@ -119,16 +176,32 @@ static int CmdGuardDemod(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf gproxii demod",
|
||||
"Try to find Guardall Prox-II preamble, if found decode / descramble data",
|
||||
"lf gproxii demod"
|
||||
"lf gproxii demod -> use graphbuffer to decode\n"
|
||||
"lf gproxii demod --raw fb8ee718ee3b8cc785c11b92 ->"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int raw_len = 0;
|
||||
uint8_t raw[12] = {0};
|
||||
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
return demodGuard(true);
|
||||
|
||||
if (raw_len != 12 && raw_len != 0) {
|
||||
PrintAndLogEx(FAILED, "Must specify 12 bytes, got " _YELLOW_("%u"), raw_len);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (raw_len == 0)
|
||||
return demodGuard(true);
|
||||
else
|
||||
return demod_guard_raw(raw, raw_len);
|
||||
}
|
||||
|
||||
static int CmdGuardReader(const char *Cmd) {
|
||||
|
|
|
@ -246,7 +246,7 @@ static int CmdHIDSim(const char *Cmd) {
|
|||
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
||||
arg_u64_0("i", NULL, "<dec>", "issue level"),
|
||||
arg_u64_0("o", "oem", "<dec>", "OEM code"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -330,7 +330,7 @@ static int CmdHIDClone(const char *Cmd) {
|
|||
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
||||
arg_int0("i", NULL, "<dec>", "issue level"),
|
||||
arg_int0("o", "oem", "<dec>", "OEM code"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
||||
arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "fileutils.h" // savefile
|
||||
#include "protocols.h" // defines
|
||||
#include "cliparser.h"
|
||||
#include "crc.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -214,7 +215,7 @@ static int CmdLFHitagEload(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "filename of dump"),
|
||||
arg_str1("f", "file", "<fn>", "Specfiy dump filename"),
|
||||
arg_lit0("1", NULL, "Card type Hitag1"),
|
||||
arg_lit0("2", NULL, "Card type Hitag2"),
|
||||
arg_lit0("s", NULL, "Card type HitagS"),
|
||||
|
@ -575,8 +576,8 @@ static int CmdLFHitagReader(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (nalen != 0 && nalen != 6) {
|
||||
PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 6, got %d", nalen);
|
||||
if (nalen != 0 && nalen != 8) {
|
||||
PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -628,7 +629,6 @@ static int CmdLFHitagReader(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.oldarg[0] == false) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
|
||||
return PM3_ESOFT;
|
||||
|
@ -657,7 +657,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "filename to load ( w/o ext )"),
|
||||
arg_str1("f", "file", "<fn>", "filename to load ( w/o ext )"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -670,22 +670,18 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
|
||||
if (fnlen > 0) {
|
||||
uint8_t *data = NULL;
|
||||
size_t datalen = 0;
|
||||
int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen);
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (datalen == (8 * 60)) {
|
||||
SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES, 1, 0, 0, data, datalen);
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Error, file length mismatch. Expected %d, got %zu", 8 * 60, datalen);
|
||||
}
|
||||
uint8_t *data = NULL;
|
||||
size_t datalen = 0;
|
||||
int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen);
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (datalen % 8 == 0) {
|
||||
SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, datalen, 0, 0, data, datalen);
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Error, file length mismatch. Expected multiple of 8, got %zu", datalen);
|
||||
}
|
||||
if (data) {
|
||||
free(data);
|
||||
}
|
||||
} else {
|
||||
SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0);
|
||||
}
|
||||
if (data) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
@ -831,7 +827,7 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "file name"),
|
||||
arg_str0("f", "file", "<fn>", "specify file name"),
|
||||
arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
|
||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
|
||||
arg_param_end
|
||||
|
@ -970,3 +966,8 @@ int CmdLFHitag(const char *Cmd) {
|
|||
int readHitagUid(void) {
|
||||
return (CmdLFHitagReader("--26") == PM3_SUCCESS);
|
||||
}
|
||||
|
||||
uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit) {
|
||||
if (nbit < 9) return 2;
|
||||
return (CRC8Hitag1Bits(d, nbit) == 0);
|
||||
}
|
||||
|
|
|
@ -19,4 +19,5 @@ int readHitagUid(void);
|
|||
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response);
|
||||
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response);
|
||||
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response);
|
||||
uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit);
|
||||
#endif
|
||||
|
|
|
@ -112,7 +112,7 @@ static int CmdIdteckClone(const char *Cmd) {
|
|||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str1("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
||||
arg_param_end
|
||||
|
@ -178,7 +178,7 @@ static int CmdIdteckSim(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str1("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -542,7 +542,7 @@ static int CmdIndalaSim(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -639,7 +639,7 @@ static int CmdIndalaClone(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_str0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_int0(NULL, "heden", "<decimal>", "Card number for Heden 2L format"),
|
||||
arg_int0(NULL, "fc", "<decimal>", "Facility code (26 bit H10301 format)"),
|
||||
arg_int0(NULL, "cn", "<decimal>", "Card number (26 bit H10301 format)"),
|
||||
|
|
|
@ -29,11 +29,11 @@ typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t;
|
|||
|
||||
static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) {
|
||||
// 255 = Not used/Unknown other values are the bit offset in the ID/FC values
|
||||
uint8_t CardToID [] = { 255, 255, 255, 255, 13, 12, 20, 5, 16, 6, 21, 17, 8, 255, 0, 7,
|
||||
const uint8_t CardToID [] = { 255, 255, 255, 255, 13, 12, 20, 5, 16, 6, 21, 17, 8, 255, 0, 7,
|
||||
10, 15, 255, 11, 4, 1, 255, 18, 255, 19, 2, 14, 3, 9, 255, 255
|
||||
};
|
||||
|
||||
uint8_t CardToFC [] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255,
|
||||
const uint8_t CardToFC [] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255,
|
||||
255, 255, 2, 255, 255, 255, 3, 255, 4, 255, 255, 255, 255, 255, 1, 255
|
||||
};
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ static int CmdMotorolaClone(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx1("r", "raw", "<hex>", "raw hex bytes. 8 bytes"),
|
||||
arg_str1("r", "raw", "<hex>", "raw hex bytes. 8 bytes"),
|
||||
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
||||
arg_param_end
|
||||
|
|
|
@ -72,7 +72,7 @@ static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) {
|
|||
static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *scambled) {
|
||||
|
||||
// 255 = Not used/Unknown other values are the bit offset in the ID/FC values
|
||||
uint8_t hex_2_id [] = {
|
||||
const uint8_t hex_2_id [] = {
|
||||
31, 27, 23, 19, 15, 11, 7, 3,
|
||||
30, 26, 22, 18, 14, 10, 6, 2,
|
||||
29, 25, 21, 17, 13, 9, 5, 1,
|
||||
|
|
|
@ -1368,7 +1368,7 @@ static bool testQ5Modulation(uint8_t mode, uint8_t modread) {
|
|||
}
|
||||
|
||||
static int convertQ5bitRate(uint8_t bitRateRead) {
|
||||
uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128};
|
||||
const uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128};
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (expected[i] == bitRateRead)
|
||||
return i;
|
||||
|
@ -1425,7 +1425,7 @@ static bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk)
|
|||
}
|
||||
|
||||
static bool testBitRate(uint8_t readRate, uint8_t clk) {
|
||||
uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128};
|
||||
const uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128};
|
||||
if (expected[readRate] == clk)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ static int CmdVikingClone(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0(NULL, "cn", "<hex>", "8 digit hex viking card number"),
|
||||
arg_str1(NULL, "cn", "<hex>", "8 digit hex viking card number"),
|
||||
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
||||
arg_param_end
|
||||
|
@ -185,7 +185,7 @@ static int CmdVikingSim(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0(NULL, "cn", "<hex>", "8 digit hex viking card number"),
|
||||
arg_str1(NULL, "cn", "<hex>", "8 digit hex viking card number"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -44,12 +44,11 @@ static uint8_t visa_chksum(uint32_t id) {
|
|||
|
||||
static uint8_t visa_parity(uint32_t id) {
|
||||
// 4bit parity LUT
|
||||
uint8_t par_lut[] = {
|
||||
0, 1, 1, 0
|
||||
, 1, 0, 0, 1
|
||||
, 1, 0, 0, 1
|
||||
, 0, 1, 1, 0
|
||||
const uint8_t par_lut[] = {
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0
|
||||
};
|
||||
|
||||
uint8_t par = 0;
|
||||
par |= par_lut[(id >> 28) & 0xF ] << 7;
|
||||
par |= par_lut[(id >> 24) & 0xF ] << 6;
|
||||
|
|
|
@ -74,6 +74,17 @@ int demodzx(bool verbose) {
|
|||
}
|
||||
|
||||
static int lf_Zx_read(void) {
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
|
||||
SendCommandNG(CMD_LF_ZX_READ, NULL, 0);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_LF_ZX_READ, &resp, 1000) == false) {
|
||||
PrintAndLogEx(ERR, "Error occurred, device did not respond during read operation.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ static int CmdNfcDecode(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("d", "data", "<hex>", "NDEF data to decode"),
|
||||
arg_str0("d", "data", "<hex>", "NDEF data to decode"),
|
||||
arg_str0("f", "file", "<fn>", "file to load"),
|
||||
arg_lit0("v", "verbose", "verbose mode"),
|
||||
arg_param_end
|
||||
|
|
|
@ -499,7 +499,7 @@ static int CmdSmartUpgrade(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "firmware file name"),
|
||||
arg_str1("f", "file", "<fn>", "Specify firmware file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -216,10 +216,11 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
case ISO_15693:
|
||||
crcStatus = iso15693_CRC_check(frame, data_len);
|
||||
break;
|
||||
case PROTO_CRYPTORF:
|
||||
case PROTO_HITAG1:
|
||||
case PROTO_HITAG2:
|
||||
case PROTO_HITAGS:
|
||||
crcStatus = hitag1_CRC_check(frame, (data_len * 8) - ((8 - parityBytes[0]) % 8));
|
||||
case PROTO_CRYPTORF:
|
||||
case PROTO_HITAG2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -240,7 +241,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
sprintf(line[0], "<empty trace - possible error>");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t partialbytebuff = 0;
|
||||
uint8_t offset = 0;
|
||||
for (int j = 0; j < data_len && j / 18 < 18; j++) {
|
||||
uint8_t parityBits = parityBytes[j >> 3];
|
||||
if (protocol != LEGIC
|
||||
|
@ -270,6 +272,18 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]);
|
||||
}
|
||||
|
||||
} else if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAG2) || (protocol == PROTO_HITAGS)) && (parityBytes[0] > 0)) {
|
||||
// handle partial bytes
|
||||
uint8_t nbits = parityBytes[0];
|
||||
if (j == 0) {
|
||||
partialbytebuff = frame[0] << nbits;
|
||||
snprintf(line[0], 120, "%02x(%i) ", frame[0] >> (8 - nbits), nbits);
|
||||
offset = 2;
|
||||
} else {
|
||||
uint8_t byte = partialbytebuff | (frame[j] >> (8 - nbits));
|
||||
partialbytebuff = frame[j] << nbits;
|
||||
snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02x ", byte);
|
||||
}
|
||||
} else {
|
||||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x ", frame[j]);
|
||||
}
|
||||
|
@ -278,11 +292,20 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
|
||||
if (markCRCBytes) {
|
||||
//CRC-command
|
||||
if (crcStatus == 0 || crcStatus == 1) {
|
||||
char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1;
|
||||
if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAGS)) && (data_len > 1)) {
|
||||
// Note that UID REQUEST response has no CRC, but we don't know
|
||||
// if the response we see is a UID
|
||||
char *pos1 = line[(data_len - 1) / 18] + (((data_len - 1) % 18) * 4) + offset - 1;
|
||||
(*pos1) = '[';
|
||||
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1;
|
||||
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) + offset - 2;
|
||||
sprintf(pos2, "%c", ']');
|
||||
} else {
|
||||
if (crcStatus == 0 || crcStatus == 1) {
|
||||
char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1;
|
||||
(*pos1) = '[';
|
||||
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1;
|
||||
sprintf(pos2, "%c", ']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +590,7 @@ static int CmdTraceLoad(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("f", "file", "<filename>", "trace file to load"),
|
||||
arg_str1("f", "file", "<fn>", "Specify trace file to load"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -606,7 +629,7 @@ static int CmdTraceSave(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("f", "file", "<filename>", "trace file to save"),
|
||||
arg_str1("f", "file", "<fn>", "Specify trace file to save"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -654,7 +677,7 @@ int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol)
|
|||
arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"),
|
||||
arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n"
|
||||
" or to import into Wireshark using encapsulation type \"ISO 14443\""),
|
||||
arg_strx0(NULL, "dict", "<file>", "use dictionary keys file"),
|
||||
arg_str0(NULL, "dict", "<file>", "use dictionary keys file"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -672,22 +695,22 @@ int CmdTraceList(const char *Cmd) {
|
|||
"Annotate trace buffer with selected protocol data\n"
|
||||
"You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n",
|
||||
"trace list -t raw -> just show raw data without annotations\n"
|
||||
"trace list -t 14a -> interpret as " _YELLOW_("ISO14443-A") " communications\n"
|
||||
"trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") " communications\n"
|
||||
"trace list -t topaz -> interpret as " _YELLOW_("Topaz") " communications\n"
|
||||
"trace list -t mf -> interpret as " _YELLOW_("MIFARE Classic") " communications and decrypt crypto1 stream\n"
|
||||
"trace list -t des -> interpret as " _YELLOW_("MIFARE DESFire") " communications\n"
|
||||
"trace list -t 14b -> interpret as " _YELLOW_("ISO14443-B") " communications\n"
|
||||
"trace list -t 7816 -> interpret as " _YELLOW_("ISO7816-4") " communications\n"
|
||||
"trace list -t 15 -> interpret as " _YELLOW_("ISO15693") " communications\n"
|
||||
"trace list -t iclass -> interpret as " _YELLOW_("iCLASS") " communications\n"
|
||||
"trace list -t legic -> interpret as " _YELLOW_("LEGIC") " communications\n"
|
||||
"trace list -t felica -> interpret as " _YELLOW_("ISO18092 / FeliCa") " communications\n"
|
||||
"trace list -t hitag1 -> interpret as " _YELLOW_("Hitag1") " communications\n"
|
||||
"trace list -t hitag2 -> interpret as " _YELLOW_("Hitag2") " communications\n"
|
||||
"trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n"
|
||||
"trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n"
|
||||
"trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n"
|
||||
"trace list -t 14a -> interpret as " _YELLOW_("ISO14443-A") "\n"
|
||||
"trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") "\n"
|
||||
"trace list -t topaz -> interpret as " _YELLOW_("Topaz") "\n"
|
||||
"trace list -t mf -> interpret as " _YELLOW_("MIFARE Classic") " and decrypt crypto1 stream\n"
|
||||
"trace list -t des -> interpret as " _YELLOW_("MIFARE DESFire") "\n"
|
||||
"trace list -t 14b -> interpret as " _YELLOW_("ISO14443-B") "\n"
|
||||
"trace list -t 7816 -> interpret as " _YELLOW_("ISO7816-4") "\n"
|
||||
"trace list -t 15 -> interpret as " _YELLOW_("ISO15693") "\n"
|
||||
"trace list -t iclass -> interpret as " _YELLOW_("iCLASS") "\n"
|
||||
"trace list -t legic -> interpret as " _YELLOW_("LEGIC") "\n"
|
||||
"trace list -t felica -> interpret as " _YELLOW_("ISO18092 / FeliCa") "\n"
|
||||
"trace list -t hitag1 -> interpret as " _YELLOW_("Hitag1") "\n"
|
||||
"trace list -t hitag2 -> interpret as " _YELLOW_("Hitag2") "\n"
|
||||
"trace list -t hitags -> interpret as " _YELLOW_("HitagS") "\n"
|
||||
"trace list -t lto -> interpret as " _YELLOW_("LTO-CM") "\n"
|
||||
"trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") "\n\n"
|
||||
"trace list -t mf --dict <mfc_default_keys> -> use dictionary keys file\n"
|
||||
"trace list -t 14a -f -> show frame delay times\n"
|
||||
"trace list -t 14a -1 -> use trace buffer "
|
||||
|
@ -702,11 +725,11 @@ int CmdTraceList(const char *Cmd) {
|
|||
arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"),
|
||||
arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n"
|
||||
" or to import into Wireshark using encapsulation type \"ISO 14443\""),
|
||||
arg_strx0("t", "type", NULL, "protocol to annotate the trace"),
|
||||
arg_strx0(NULL, "dict", "<file>", "use dictionary keys file"),
|
||||
arg_str0("t", "type", NULL, "protocol to annotate the trace"),
|
||||
arg_str0(NULL, "dict", "<fn>", "use dictionary keys file"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
bool use_buffer = arg_get_lit(ctx, 1);
|
||||
bool show_wait_cycles = arg_get_lit(ctx, 2);
|
||||
|
@ -752,6 +775,11 @@ int CmdTraceList(const char *Cmd) {
|
|||
else if (strcmp(type, "lto") == 0) protocol = LTO;
|
||||
else if (strcmp(type, "cryptorf") == 0) protocol = PROTO_CRYPTORF;
|
||||
else if (strcmp(type, "raw") == 0) protocol = -1;
|
||||
else if (strcmp(type, "") == 0) protocol = -1;
|
||||
else {
|
||||
PrintAndLogEx(FAILED, "Unknown protocol \"%s\"", type);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (use_buffer == false) {
|
||||
download_trace();
|
||||
|
|
|
@ -113,7 +113,7 @@ int CmdWiegandDecode(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("r", "raw", "<hex>", "raw hex to be decoded"),
|
||||
arg_str0("r", "raw", "<hex>", "raw hex to be decoded"),
|
||||
arg_str0("b", "bin", "<bin>", "binary string to be decoded"),
|
||||
arg_param_end
|
||||
};
|
||||
|
|
|
@ -81,10 +81,10 @@ static int CmdEMVSelect(const char *Cmd) {
|
|||
arg_param_begin,
|
||||
arg_lit0("sS", "select", "activate field and select card"),
|
||||
arg_lit0("kK", "keep", "keep field for next command"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("aA", "apdu", "show APDU requests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
|
||||
arg_str1(NULL, NULL, "<hex>", "Applet AID"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -247,7 +247,7 @@ static int CmdEMVGPO(const char *Cmd) {
|
|||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
|
||||
arg_strx0(NULL, NULL, "<hex>", "PDOLdata/PDOL"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -354,7 +354,7 @@ static int CmdEMVReadRecord(const char *Cmd) {
|
|||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrecord 1byte HEX>", NULL),
|
||||
arg_strx1(NULL, NULL, "<hex>", "<SFI 1 byte><SFIrecord 1 byte"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -418,7 +418,7 @@ static int CmdEMVAC(const char *Cmd) {
|
|||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
|
||||
arg_strx1(NULL, NULL, "<hex>", "CDOLdata/CDOL"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -590,7 +590,7 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
|
|||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
|
||||
arg_strx1(NULL, NULL, "<hex>", "DDOLdata/DDOL"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -1442,7 +1442,7 @@ static int CmdEMVScan(const char *Cmd) {
|
|||
arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
|
||||
arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_str1(NULL, NULL, "output.json", "JSON output file name"),
|
||||
arg_str1(NULL, NULL, "<fn>", "JSON output filename"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -411,11 +411,15 @@ static void flash_suggest_update_bootloader(void) {
|
|||
|
||||
PrintAndLogEx(ERR, _RED_("It is recommended that you first" _YELLOW_(" update your bootloader") _RED_(" alone,")));
|
||||
PrintAndLogEx(ERR, _RED_("reboot the Proxmark3 then only update the main firmware") "\n");
|
||||
PrintAndLogEx(ERR, "Follow these steps :");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(ERR, "------------- " _CYAN_("Follow these steps") " -------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(ERR, " 1) ./pm3-flash-bootrom");
|
||||
PrintAndLogEx(ERR, " 2) ./pm3-flash-all");
|
||||
PrintAndLogEx(ERR, " 3) ./pm3");
|
||||
PrintAndLogEx(INFO, "--------------------------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "---------------------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
gs_printed_msg = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,82 +93,82 @@ MAKE_ENUM_TYPE(uint8_t);
|
|||
|
||||
// KSX6924LookupCardType
|
||||
MAKE_ENUM_CONST(CardType, uint8_t,
|
||||
{ 0x00, "Pre-paid" },
|
||||
{ 0x10, "Post-pay" },
|
||||
{ 0x20, "Mobile post-pay" },
|
||||
);
|
||||
{ 0x00, "Pre-paid" },
|
||||
{ 0x10, "Post-pay" },
|
||||
{ 0x20, "Mobile post-pay" },
|
||||
);
|
||||
|
||||
// KSX6924LookupAlg
|
||||
MAKE_ENUM_CONST(Alg, uint8_t,
|
||||
{ 0x00, "SEED" },
|
||||
{ 0x10, "3DES" },
|
||||
);
|
||||
{ 0x00, "SEED" },
|
||||
{ 0x10, "3DES" },
|
||||
);
|
||||
|
||||
// KSX6924LookupTMoneyIDCenter
|
||||
MAKE_ENUM_CONST(TMoneyIDCenter, uint8_t,
|
||||
{ 0x00, "reserved" },
|
||||
{ 0x01, "Korea Financial Telecommunications and Clearings Institute" },
|
||||
{ 0x02, "A-Cash" },
|
||||
{ 0x03, "Mybi" },
|
||||
{ 0x00, "reserved" },
|
||||
{ 0x01, "Korea Financial Telecommunications and Clearings Institute" },
|
||||
{ 0x02, "A-Cash" },
|
||||
{ 0x03, "Mybi" },
|
||||
|
||||
{ 0x05, "V-Cash" },
|
||||
{ 0x06, "Mondex Korea" },
|
||||
{ 0x07, "Korea Expressway Corporation" },
|
||||
{ 0x08, "Korea Smart Card Corporation" },
|
||||
{ 0x09, "KORAIL Networks" },
|
||||
{ 0x05, "V-Cash" },
|
||||
{ 0x06, "Mondex Korea" },
|
||||
{ 0x07, "Korea Expressway Corporation" },
|
||||
{ 0x08, "Korea Smart Card Corporation" },
|
||||
{ 0x09, "KORAIL Networks" },
|
||||
|
||||
{ 0x0b, "EB Card Corporation" },
|
||||
{ 0x0c, "Seoul Bus Transport Association" },
|
||||
{ 0x0d, "Cardnet" },
|
||||
);
|
||||
{ 0x0b, "EB Card Corporation" },
|
||||
{ 0x0c, "Seoul Bus Transport Association" },
|
||||
{ 0x0d, "Cardnet" },
|
||||
);
|
||||
|
||||
// KSX6924LookupTMoneyUserCode
|
||||
MAKE_ENUM_CONST(TMoneyUserCode, uint8_t,
|
||||
{ 0x01, "Regular/normal" },
|
||||
{ 0x02, "Child" },
|
||||
{ 0x01, "Regular/normal" },
|
||||
{ 0x02, "Child" },
|
||||
|
||||
{ 0x04, "Youth" },
|
||||
{ 0x04, "Youth" },
|
||||
|
||||
{ 0x06, "elderly" },
|
||||
{ 0x06, "elderly" },
|
||||
|
||||
{ 0x0f, "Test" },
|
||||
{ 0xff, "Inactive" },
|
||||
);
|
||||
{ 0x0f, "Test" },
|
||||
{ 0xff, "Inactive" },
|
||||
);
|
||||
|
||||
// KSX6924LookupTMoneyDisRate
|
||||
MAKE_ENUM_CONST(TMoneyDisRate, uint8_t,
|
||||
{ 0x00, "No discount" },
|
||||
{ 0x00, "No discount" },
|
||||
|
||||
{ 0x10, "Disabled, basic" },
|
||||
{ 0x11, "Disabled, companion" },
|
||||
{ 0x10, "Disabled, basic" },
|
||||
{ 0x11, "Disabled, companion" },
|
||||
|
||||
{ 0x20, "Merit, basic" },
|
||||
{ 0x21, "Merit, companion" },
|
||||
);
|
||||
{ 0x20, "Merit, basic" },
|
||||
{ 0x21, "Merit, companion" },
|
||||
);
|
||||
|
||||
// KSX6924LookupTMoneyTCode
|
||||
MAKE_ENUM_CONST(TMoneyTCode, uint8_t,
|
||||
{ 0x00, "None" },
|
||||
{ 0x01, "SK Telecom" },
|
||||
{ 0x02, "Korea Telecom" },
|
||||
{ 0x03, "LG Uplus" },
|
||||
);
|
||||
{ 0x00, "None" },
|
||||
{ 0x01, "SK Telecom" },
|
||||
{ 0x02, "Korea Telecom" },
|
||||
{ 0x03, "LG Uplus" },
|
||||
);
|
||||
|
||||
// KSX6924LookupTMoneyCCode
|
||||
MAKE_ENUM_CONST(TMoneyCCode, uint8_t,
|
||||
{ 0x00, "None" },
|
||||
{ 0x01, "KB Kookmin Bank" },
|
||||
{ 0x02, "Nonghyup Bank" },
|
||||
{ 0x03, "Lotte Card" },
|
||||
{ 0x04, "BC Card" },
|
||||
{ 0x05, "Samsung Card" },
|
||||
{ 0x06, "Shinhan Bank" },
|
||||
{ 0x07, "Citibank Korea" },
|
||||
{ 0x08, "Korea Exchange Bank" },
|
||||
{ 0x09, "Woori" },
|
||||
{ 0x0a, "Hana SK Card" },
|
||||
{ 0x0b, "Hyundai Capital Services" },
|
||||
);
|
||||
{ 0x00, "None" },
|
||||
{ 0x01, "KB Kookmin Bank" },
|
||||
{ 0x02, "Nonghyup Bank" },
|
||||
{ 0x03, "Lotte Card" },
|
||||
{ 0x04, "BC Card" },
|
||||
{ 0x05, "Samsung Card" },
|
||||
{ 0x06, "Shinhan Bank" },
|
||||
{ 0x07, "Citibank Korea" },
|
||||
{ 0x08, "Korea Exchange Bank" },
|
||||
{ 0x09, "Woori" },
|
||||
{ 0x0a, "Hana SK Card" },
|
||||
{ 0x0b, "Hyundai Capital Services" },
|
||||
);
|
||||
|
||||
static const char *KSX6924_UNKNOWN = "Unknown";
|
||||
|
||||
|
@ -226,7 +226,7 @@ static int64_t bcdToLong(const uint8_t *buf, size_t len) {
|
|||
/**
|
||||
* Converts a date from on-card format to ksx6924_date format.
|
||||
*/
|
||||
static bool convert_internal_date( const _ksx6924_internal_date_t i, struct ksx6924_date *ret) {
|
||||
static bool convert_internal_date(const _ksx6924_internal_date_t i, struct ksx6924_date *ret) {
|
||||
|
||||
int64_t year = bcdToLong(i.year, 2);
|
||||
int16_t month = bcdToInteger(i.month[0]);
|
||||
|
@ -276,7 +276,7 @@ bool KSX6924ParsePurseInfo(const uint8_t *purseInfo, size_t purseLen, struct ksx
|
|||
0, // min_str_len
|
||||
0, // spaces_between
|
||||
false // uppercase
|
||||
);
|
||||
);
|
||||
|
||||
int64_t idtr = bcdToLong(internalPurseInfo->idtr, 5);
|
||||
if (idtr < 0) {
|
||||
|
@ -294,8 +294,8 @@ bool KSX6924ParsePurseInfo(const uint8_t *purseInfo, size_t purseLen, struct ksx
|
|||
convert_internal_date(internalPurseInfo->issueDate, &(ret->issueDate));
|
||||
convert_internal_date(internalPurseInfo->expiryDate, &(ret->expiryDate));
|
||||
|
||||
ret->balMax = MemBeToUint4byte((uint8_t*)internalPurseInfo->balMax);
|
||||
ret->mmax = MemBeToUint4byte((uint8_t*)internalPurseInfo->mmax);
|
||||
ret->balMax = MemBeToUint4byte((uint8_t *)internalPurseInfo->balMax);
|
||||
ret->mmax = MemBeToUint4byte((uint8_t *)internalPurseInfo->mmax);
|
||||
|
||||
memcpy(&ret->rfu, &internalPurseInfo->rfu, 8);
|
||||
|
||||
|
@ -367,7 +367,7 @@ int KSX6924Select(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t
|
|||
ResultLen,
|
||||
sw,
|
||||
NULL
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -390,7 +390,7 @@ bool KSX6924TrySelect(void) {
|
|||
"Not a KS X 6924 card! APDU response: %04x - %s",
|
||||
sw,
|
||||
GetAPDUCodeDescription(sw >> 8, sw & 0xff)
|
||||
);
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "APDU exchange error. Card returns 0x0000.");
|
||||
}
|
||||
|
@ -430,8 +430,8 @@ bool KSX6924GetBalance(uint32_t *result) {
|
|||
return false;
|
||||
}
|
||||
|
||||
*result = MemBeToUint4byte((uint8_t*)arr);
|
||||
return true;
|
||||
*result = MemBeToUint4byte((uint8_t *)arr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -448,7 +448,7 @@ bool KSX6924InitializeCard(uint8_t mpda1, uint8_t mpda2, uint8_t mpda3, uint8_t
|
|||
uint16_t sw = 0;
|
||||
size_t rlen = 0;
|
||||
|
||||
// ALGep + VKep + BALep + IDcenter + IDep + NTep + Sign1 + sw
|
||||
// ALGep + VKep + BALep + IDcenter + IDep + NTep + Sign1 + sw
|
||||
uint8_t arr[1 + 1 + 4 + 1 + 8 + 4 + 4 + 2];
|
||||
memset(arr, 0, sizeof(arr));
|
||||
|
||||
|
|
|
@ -90,8 +90,7 @@ bool KSX6924InitializeCard(uint8_t mpda1, uint8_t mpda2, uint8_t mpda3, uint8_t
|
|||
|
||||
// Proprietary get record command. Function unknown.
|
||||
// result must be 10 bytes long.
|
||||
bool KSX6924ProprietaryGetRecord(
|
||||
uint8_t id, uint8_t *result, size_t resultLen);
|
||||
bool KSX6924ProprietaryGetRecord(uint8_t id, uint8_t *result, size_t result_len);
|
||||
|
||||
#endif /* __KSX6924CORE_H__ */
|
||||
|
||||
|
|
|
@ -267,10 +267,10 @@ static bool DesfireISOChannelValidCmd(uint8_t cmd) {
|
|||
}
|
||||
|
||||
static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
size_t rlen = 0;
|
||||
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
|
@ -279,6 +279,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
if (srcdatalen < hdrlen)
|
||||
hdrlen = srcdatalen;
|
||||
|
||||
size_t rlen;
|
||||
|
||||
if (ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) {
|
||||
if (srcdatalen == 0) {
|
||||
free(data);
|
||||
|
@ -330,14 +332,15 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
*dstdatalen = rlen;
|
||||
ctx->commMode = DCMEncrypted;
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
size_t rlen = 0;
|
||||
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
|
@ -346,6 +349,8 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
if (srcdatalen < hdrlen)
|
||||
hdrlen = srcdatalen;
|
||||
|
||||
size_t rlen;
|
||||
|
||||
// we calc MAC anyway
|
||||
// if encypted channel and no data - we only calc MAC
|
||||
if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) {
|
||||
|
@ -360,6 +365,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx));
|
||||
*dstdatalen = srcdatalen + DesfireGetMACLength(ctx);
|
||||
}
|
||||
|
||||
} else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding) {
|
||||
uint8_t paddinglen = (ctx->commMode == DCMEncryptedWithPadding) ? 1 : 0;
|
||||
rlen = padded_data_length(srcdatalen + 4 + paddinglen - hdrlen, desfire_get_key_block_length(ctx->keyType));
|
||||
|
@ -395,10 +401,10 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
}
|
||||
|
||||
static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
size_t rlen = 0;
|
||||
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
|
@ -416,6 +422,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
} else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding || ctx->commMode == DCMEncryptedPlain) {
|
||||
memcpy(dstdata, srcdata, hdrlen);
|
||||
|
||||
size_t rlen = 0;
|
||||
if (srcdatalen > hdrlen) {
|
||||
rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType));
|
||||
memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen);
|
||||
|
@ -437,10 +444,10 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
}
|
||||
|
||||
static void DesfireSecureChannelEncodeLRP(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
size_t rlen = 0;
|
||||
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
|
@ -458,6 +465,7 @@ static void DesfireSecureChannelEncodeLRP(DesfireContext_t *ctx, uint8_t cmd, ui
|
|||
} else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding || ctx->commMode == DCMEncryptedPlain) {
|
||||
memcpy(dstdata, srcdata, hdrlen);
|
||||
|
||||
size_t rlen = 0;
|
||||
if (srcdatalen > hdrlen) {
|
||||
rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType));
|
||||
memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen);
|
||||
|
@ -502,10 +510,10 @@ void DesfireSecureChannelEncode(DesfireContext_t *ctx, uint8_t cmd, uint8_t *src
|
|||
}
|
||||
|
||||
static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
size_t rlen = 0;
|
||||
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
|
@ -515,7 +523,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdat
|
|||
size_t maclen = DesfireGetMACLength(ctx);
|
||||
if (srcdatalen > maclen && DesfireEV1D40ReceiveMAC(ctx, ctx->lastCommand)) {
|
||||
uint8_t mac[16] = {0};
|
||||
rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType));
|
||||
size_t rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType));
|
||||
memcpy(data, srcdata, srcdatalen - maclen);
|
||||
DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, rlen, NULL, true, true, mac);
|
||||
|
||||
|
@ -562,7 +570,8 @@ static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdat
|
|||
}
|
||||
|
||||
static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t));
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
|
@ -736,13 +745,14 @@ static void DesfireSecureChannelDecodeLRP(DesfireContext_t *ctx, uint8_t *srcdat
|
|||
static void DesfireISODecode(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) {
|
||||
memcpy(dstdata, srcdata, srcdatalen);
|
||||
*dstdatalen = srcdatalen;
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (srcdatalen < DesfireGetMACLength(ctx))
|
||||
return;
|
||||
|
||||
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
uint8_t maclen = DesfireGetMACLength(ctx);
|
||||
if (DesfireIsAuthenticated(ctx)) {
|
||||
memcpy(data, srcdata, srcdatalen - maclen);
|
||||
|
|
|
@ -1069,18 +1069,21 @@ int mfGen3Freeze(void) {
|
|||
}
|
||||
}
|
||||
|
||||
int mfG3GetBlock(uint8_t blockno, uint8_t *data) {
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data) {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
} PACKED payload;
|
||||
payload.blockno = blockno;
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t *)&payload, sizeof(payload));
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
memcpy(data, resp.data.asBytes, 16);
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
|
|
|
@ -85,7 +85,7 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid);
|
|||
int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock);
|
||||
int mfGen3Freeze(void);
|
||||
|
||||
int mfG3GetBlock(uint8_t blockno, uint8_t *data);
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data);
|
||||
|
||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#ifndef LIBPM3
|
||||
#define BANNERMSG1 ""
|
||||
#define BANNERMSG2 " [ :snowflake: Iceman :snowflake: ]"
|
||||
#define BANNERMSG2 " [ Iceman :snowflake: ]"
|
||||
#define BANNERMSG3 ""
|
||||
|
||||
typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode;
|
||||
|
|
|
@ -47,7 +47,7 @@ double g_PlotGridX = 0, g_PlotGridY = 0, g_PlotGridXdefault = 64, g_PlotGridYdef
|
|||
uint32_t g_CursorCPos = 0, g_CursorDPos = 0, g_GraphStop = 0;
|
||||
uint32_t g_GraphStart = 0; // Starting point/offset for the left side of the graph
|
||||
double g_GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis)
|
||||
static bool flushAfterWrite = 0;
|
||||
static bool flushAfterWrite = false;
|
||||
double g_GridOffset = 0;
|
||||
bool g_GridLocked = false;
|
||||
|
||||
|
@ -411,6 +411,10 @@ void SetFlushAfterWrite(bool value) {
|
|||
flushAfterWrite = value;
|
||||
}
|
||||
|
||||
bool GetFlushAfterWrite(void) {
|
||||
return flushAfterWrite;
|
||||
}
|
||||
|
||||
void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n) {
|
||||
uint8_t *rdest = (uint8_t *)dest;
|
||||
uint8_t *rsrc = (uint8_t *)src;
|
||||
|
|
|
@ -63,6 +63,7 @@ extern session_arg_t g_session;
|
|||
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space);
|
||||
void PrintAndLogEx(logLevel_t level, const char *fmt, ...);
|
||||
void SetFlushAfterWrite(bool value);
|
||||
bool GetFlushAfterWrite(void);
|
||||
void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter);
|
||||
void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n);
|
||||
void memcpy_filter_emoji(void *dest, const void *src, size_t n, emojiMode_t mode);
|
||||
|
|
|
@ -1414,7 +1414,7 @@ int HIDFindCardFormat(const char *format) {
|
|||
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
|
||||
memset(packed, 0, sizeof(wiegand_message_t));
|
||||
|
||||
if (format_idx < 0 || format_idx >= ARRAYLEN(FormatTable))
|
||||
if (format_idx < 0 || format_idx >= ARRAYLEN(FormatTable) - 1)
|
||||
return false;
|
||||
|
||||
return FormatTable[format_idx].Pack(card, packed, preamble);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue