Merge remote-tracking branch 'upstream/master' into feat/hf-gallagher

This commit is contained in:
Matt Moran 2022-01-05 23:56:33 +13:00
commit de30ba90d1
116 changed files with 3007 additions and 1860 deletions

View file

@ -1464,4 +1464,14 @@ B5ADEFCA46C4
BF3FE47637EC
B290401B0CAD
AD11006B0601
#
# Data from Mifare Classic Tool repo
# Armenian Metro
E4410EF8ED2D
6A68A7D83E11
0D6057E8133B
D3F3B958B8A3
3E120568A35C
2196FAD8115B
7C469FE86855
CE99FBC8BD26

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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++) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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__ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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