This commit is contained in:
iceman1001 2025-06-06 19:00:34 +02:00
commit 53e1e32409
3 changed files with 114 additions and 85 deletions

View file

@ -3913,13 +3913,14 @@ static int CmdHFiClassView(const char *Cmd) {
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite) { void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite) {
if (elite) { if (elite) {
uint8_t keytable[128] = {0}; uint8_t keytable[128] = {0};
uint8_t key_index[8] = {0}; uint8_t key_index[PICOPASS_BLOCK_SIZE] = {0};
uint8_t key_sel[8] = { 0 }; uint8_t key_sel[PICOPASS_BLOCK_SIZE] = {0};
uint8_t key_sel_p[8] = { 0 }; uint8_t key_sel_p[PICOPASS_BLOCK_SIZE] = {0};
hash2(KEY, keytable); hash2(KEY, keytable);
hash1(CSN, key_index); hash1(CSN, key_index);
for (uint8_t i = 0; i < 8 ; i++) for (uint8_t i = 0; i < 8 ; i++) {
key_sel[i] = keytable[key_index[i]]; key_sel[i] = keytable[key_index[i]];
}
//Permute from iclass format to standard format //Permute from iclass format to standard format
permutekey_rev(key_sel, key_sel_p); permutekey_rev(key_sel, key_sel_p);
@ -4249,7 +4250,7 @@ static void add_key(uint8_t *key) {
static int CmdHFiClassCheckKeys(const char *Cmd) { static int CmdHFiClassCheckKeys(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass chk", CLIParserInit(&ctx, "hf iclass chk",
"Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag", "Checkkeys loads a dictionary text file with 8 byte hex keys to test authenticating against a iCLASS tag",
"hf iclass chk -f iclass_default_keys.dic\n" "hf iclass chk -f iclass_default_keys.dic\n"
"hf iclass chk -f iclass_elite_keys.dic --elite\n" "hf iclass chk -f iclass_elite_keys.dic --elite\n"
"hf iclass chk --vb6kdf\n"); "hf iclass chk --vb6kdf\n");
@ -4525,7 +4526,7 @@ void picopass_elite_nextKey(uint8_t *key) {
} }
prepared = true; prepared = true;
} }
memcpy(key, key_state, 8); memcpy(key, key_state, PICOPASS_BLOCK_SIZE);
} }
static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, uint8_t no_first_auth[8], bool debug, bool test, bool fast, bool short_delay, bool allnight) { static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, uint8_t no_first_auth[8], bool debug, bool test, bool fast, bool short_delay, bool allnight) {
@ -4759,12 +4760,20 @@ static int CmdHFiClassLegBrute(const char *Cmd) {
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int epurse_len = 0, macs_len = 0, macs2_len = 0, startingkey_len = 0; int epurse_len = 0;
uint8_t epurse[PICOPASS_BLOCK_SIZE] = {0}, macs[PICOPASS_BLOCK_SIZE] = {0}, macs2[PICOPASS_BLOCK_SIZE] = {0}, startingKey[PICOPASS_BLOCK_SIZE] = {0}; uint8_t epurse[PICOPASS_BLOCK_SIZE] = {0};
CLIGetHexWithReturn(ctx, 1, epurse, &epurse_len); CLIGetHexWithReturn(ctx, 1, epurse, &epurse_len);
int macs_len = 0;
uint8_t macs[PICOPASS_BLOCK_SIZE] = {0};
CLIGetHexWithReturn(ctx, 2, macs, &macs_len); CLIGetHexWithReturn(ctx, 2, macs, &macs_len);
int macs2_len = 0;
uint8_t macs2[PICOPASS_BLOCK_SIZE] = {0};
CLIGetHexWithReturn(ctx, 3, macs2, &macs2_len); CLIGetHexWithReturn(ctx, 3, macs2, &macs2_len);
int startingkey_len = 0;
uint8_t startingKey[PICOPASS_BLOCK_SIZE] = {0};
CLIGetHexWithReturn(ctx, 4, startingKey, &startingkey_len); CLIGetHexWithReturn(ctx, 4, startingKey, &startingkey_len);
uint64_t index = arg_get_int_def(ctx, 5, 0); uint64_t index = arg_get_int_def(ctx, 5, 0);
@ -4909,7 +4918,7 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass legrec", CLIParserInit(&ctx, "hf iclass legrec",
"Attempts to recover the diversified key of a specific iClass card. This may take several days.\n" "Attempts to recover the diversified key of a specific iCLASS card. This may take several days.\n"
"The card must remain be on the PM3 antenna during the whole process.\n" "The card must remain be on the PM3 antenna during the whole process.\n"
_RED_(" ! Warning ! ") _WHITE_(" This process may brick the card! ") _RED_(" ! Warning ! "), _RED_(" ! Warning ! ") _WHITE_(" This process may brick the card! ") _RED_(" ! Warning ! "),
"hf iclass legrec --macs 0000000089cb984b\n" "hf iclass legrec --macs 0000000089cb984b\n"
@ -5124,7 +5133,7 @@ static int CmdHFiClassLookUp(const char *Cmd) {
uint8_t *keyBlock = NULL; uint8_t *keyBlock = NULL;
uint32_t keycount = 0; uint32_t keycount = 0;
if (!use_vb6kdf) { if (use_vb6kdf == false) {
// Load keys // Load keys
int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount); int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount);
if (res != PM3_SUCCESS || keycount == 0) { if (res != PM3_SUCCESS || keycount == 0) {
@ -5176,7 +5185,6 @@ static int CmdHFiClassLookUp(const char *Cmd) {
// Binsearch // Binsearch
item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32);
if (item != NULL) { if (item != NULL) {
PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex(item->key, 8)); PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex(item->key, 8));
add_key(item->key); add_key(item->key);
@ -5219,23 +5227,24 @@ static void *bf_generate_mac(void *thread_arg) {
uint8_t *keys = targ->keys; uint8_t *keys = targ->keys;
iclass_premac_t *list = targ->list.premac; iclass_premac_t *list = targ->list.premac;
uint8_t csn[8]; uint8_t csn[PICOPASS_BLOCK_SIZE];
uint8_t cc_nr[12]; uint8_t cc_nr[12];
memcpy(csn, targ->csn, sizeof(csn)); memcpy(csn, targ->csn, sizeof(csn));
memcpy(cc_nr, targ->cc_nr, sizeof(cc_nr)); memcpy(cc_nr, targ->cc_nr, sizeof(cc_nr));
uint8_t key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t key[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
for (uint32_t i = idx; i < keycnt; i += iclass_tc) { for (uint32_t i = idx; i < keycnt; i += iclass_tc) {
memcpy(key, keys + 8 * i, 8); memcpy(key, keys + 8 * i, PICOPASS_BLOCK_SIZE);
pthread_mutex_lock(&generator_mutex); pthread_mutex_lock(&generator_mutex);
if (use_raw) if (use_raw) {
memcpy(div_key, key, 8); memcpy(div_key, key, PICOPASS_BLOCK_SIZE);
else } else {
HFiClassCalcDivKey(csn, key, div_key, use_elite); HFiClassCalcDivKey(csn, key, div_key, use_elite);
}
doMAC(cc_nr, div_key, list[i].mac); doMAC(cc_nr, div_key, list[i].mac);
pthread_mutex_unlock(&generator_mutex); pthread_mutex_unlock(&generator_mutex);
@ -5289,22 +5298,23 @@ static void *bf_generate_mackey(void *thread_arg) {
uint8_t *keys = targ->keys; uint8_t *keys = targ->keys;
iclass_prekey_t *list = targ->list.prekey; iclass_prekey_t *list = targ->list.prekey;
uint8_t csn[8]; uint8_t csn[PICOPASS_BLOCK_SIZE];
uint8_t cc_nr[12]; uint8_t cc_nr[12];
memcpy(csn, targ->csn, sizeof(csn)); memcpy(csn, targ->csn, sizeof(csn));
memcpy(cc_nr, targ->cc_nr, sizeof(cc_nr)); memcpy(cc_nr, targ->cc_nr, sizeof(cc_nr));
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
for (uint32_t i = idx; i < keycnt; i += iclass_tc) { for (uint32_t i = idx; i < keycnt; i += iclass_tc) {
memcpy(list[i].key, keys + 8 * i, 8); memcpy(list[i].key, keys + 8 * i, PICOPASS_BLOCK_SIZE);
pthread_mutex_lock(&generator_mutex); pthread_mutex_lock(&generator_mutex);
if (use_raw) if (use_raw) {
memcpy(div_key, list[i].key, 8); memcpy(div_key, list[i].key, PICOPASS_BLOCK_SIZE);
else } else {
HFiClassCalcDivKey(csn, list[i].key, div_key, use_elite); HFiClassCalcDivKey(csn, list[i].key, div_key, use_elite);
}
doMAC(cc_nr, div_key, list[i].mac); doMAC(cc_nr, div_key, list[i].mac);
pthread_mutex_unlock(&generator_mutex); pthread_mutex_unlock(&generator_mutex);
@ -5340,17 +5350,19 @@ void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elit
} }
} }
for (int i = 0; i < iclass_tc; i++) for (int i = 0; i < iclass_tc; i++) {
pthread_join(threads[i], NULL); pthread_join(threads[i], NULL);
}
} }
// print diversified keys // print diversified keys
void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list) { void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list) {
iclass_prekey_t *b = calloc(keycnt, sizeof(iclass_prekey_t)); iclass_prekey_t *b = calloc(keycnt, sizeof(iclass_prekey_t));
if (!b) if (b == NULL) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
return; return;
}
for (uint32_t i = 0; i < keycnt; i++) { for (uint32_t i = 0; i < keycnt; i++) {
memcpy(b[i].key, keys + 8 * i, 8); memcpy(b[i].key, keys + 8 * i, 8);
@ -5423,31 +5435,27 @@ static void shave(uint8_t *data, uint8_t len) {
} }
static void generate_rev(uint8_t *data, uint8_t len) { static void generate_rev(uint8_t *data, uint8_t len) {
uint8_t *key = calloc(len, sizeof(uint8_t)); uint8_t *key = calloc(len, sizeof(uint8_t));
PrintAndLogEx(SUCCESS, "input permuted key | %s \n", sprint_hex(data, len)); PrintAndLogEx(SUCCESS, "permuted key..... %s", sprint_hex_inrow(data, len));
permute_rev(data, len, key); permute_rev(data, len, key);
PrintAndLogEx(SUCCESS, " unpermuted key | %s \n", sprint_hex(key, len)); PrintAndLogEx(SUCCESS, "unpermuted key... %s", sprint_hex_inrow(key, len));
shave(key, len); shave(key, len);
PrintAndLogEx(SUCCESS, " key | %s \n", sprint_hex(key, len)); PrintAndLogEx(SUCCESS, "key.............. %s", sprint_hex_inrow(key, len));
free(key); free(key);
} }
static void generate(uint8_t *data, uint8_t len) { static void generate(uint8_t *data, uint8_t len) {
uint8_t *key = calloc(len, sizeof(uint8_t)); uint8_t *key = calloc(len, sizeof(uint8_t));
uint8_t *pkey = calloc(len, sizeof(uint8_t)); uint8_t *pkey = calloc(len, sizeof(uint8_t));
PrintAndLogEx(SUCCESS, " input key | %s \n", sprint_hex(data, len)); PrintAndLogEx(SUCCESS, "input key...... %s", sprint_hex_inrow(data, len));
permute(data, len, pkey); permute(data, len, pkey);
PrintAndLogEx(SUCCESS, "permuted key | %s \n", sprint_hex(pkey, len)); PrintAndLogEx(SUCCESS, "permuted key... %s", sprint_hex_inrow(pkey, len));
simple_crc(pkey, len, key); simple_crc(pkey, len, key);
PrintAndLogEx(SUCCESS, " CRC'ed key | %s \n", sprint_hex(key, len)); PrintAndLogEx(SUCCESS, "CRC'ed key..... %s", sprint_hex_inrow(key, len));
free(key); free(key);
free(pkey); free(pkey);
} }
static int CmdHFiClassPermuteKey(const char *Cmd) { static int CmdHFiClassPermuteKey(const char *Cmd) {
uint8_t key[8] = {0};
uint8_t data[16] = {0};
int len = 0;
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass permutekey", CLIParserInit(&ctx, "hf iclass permutekey",
"Permute function from 'heart of darkness' paper.", "Permute function from 'heart of darkness' paper.",
@ -5461,22 +5469,29 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool isReverse = arg_get_lit(ctx, 1); bool isReverse = arg_get_lit(ctx, 1);
CLIGetHexWithReturn(ctx, 2, data, &len);
int dlen = 0;
uint8_t data[16] = {0};
CLIGetHexWithReturn(ctx, 2, data, &dlen);
CLIParserFree(ctx); CLIParserFree(ctx);
memcpy(key, data, 8); uint8_t key[PICOPASS_BLOCK_SIZE] = {0};
memcpy(key, data, PICOPASS_BLOCK_SIZE);
if (isReverse) { if (isReverse) {
generate_rev(data, len); generate_rev(data, dlen);
uint8_t key_std_format[8] = {0}; uint8_t key_std_format[PICOPASS_BLOCK_SIZE] = {0};
permutekey_rev(key, key_std_format); permutekey_rev(key, key_std_format);
PrintAndLogEx(SUCCESS, "Standard NIST format key " _YELLOW_("%s") " \n", sprint_hex(key_std_format, 8)); PrintAndLogEx(SUCCESS, "Standard NIST format key..... " _YELLOW_("%s"), sprint_hex_inrow(key_std_format, PICOPASS_BLOCK_SIZE));
PrintAndLogEx(NORMAL, "");
} else { } else {
generate(data, len); generate(data, dlen);
uint8_t key_iclass_format[8] = {0}; uint8_t key_iclass_format[PICOPASS_BLOCK_SIZE] = {0};
permutekey(key, key_iclass_format); permutekey(key, key_iclass_format);
PrintAndLogEx(SUCCESS, "HID permuted iCLASS format: %s \n", sprint_hex(key_iclass_format, 8)); PrintAndLogEx(SUCCESS, "HID permuted iCLASS format... " _YELLOW_("%s"), sprint_hex_inrow(key_iclass_format, PICOPASS_BLOCK_SIZE));
PrintAndLogEx(NORMAL, "");
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -5486,12 +5501,12 @@ static int CmdHFiClassEncode(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass encode", CLIParserInit(&ctx, "hf iclass encode",
"Encode binary wiegand to block 7,8,9\n" "Encode binary wiegand to block 7,8,9\n"
"Use either --bin or --wiegand/--fc/--cn", "Use either --bin or --wiegand/--fc/--cn\n"
"When using emulator you have to first load a credential into emulator memory",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n" "hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n" "hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key\n" "hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key\n"
"hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory\n" "hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory"
"When using emulator you have to first load a credential into emulator memory"
); );
void *argtable[] = { void *argtable[] = {
@ -5852,8 +5867,8 @@ static int CmdHFiClassSAM(const char *Cmd) {
CLIParserInit(&ctx, "hf iclass sam", CLIParserInit(&ctx, "hf iclass sam",
"Extract PACS via a HID SAM\n", "Extract PACS via a HID SAM\n",
"hf iclass sam\n" "hf iclass sam\n"
"hf iclass sam -p -d a005a103800104 -> get PACS data, but ensure that epurse will stay unchanged\n" "hf iclass sam -p -d a005a103800104 -> get PACS data, prevent epurse update\n"
"hf iclass sam --break-on-nr-mac -> get Nr-MAC for extracting encrypted SIO\n" "hf iclass sam --break -> get Nr-MAC for extracting encrypted SIO\n"
); );
void *argtable[] = { void *argtable[] = {
@ -5862,8 +5877,8 @@ static int CmdHFiClassSAM(const char *Cmd) {
arg_lit0("k", "keep", "keep the field active after command executed"), arg_lit0("k", "keep", "keep the field active after command executed"),
arg_lit0("n", "nodetect", "skip selecting the card and sending card details to SAM"), arg_lit0("n", "nodetect", "skip selecting the card and sending card details to SAM"),
arg_lit0("t", "tlv", "decode TLV"), arg_lit0("t", "tlv", "decode TLV"),
arg_lit0(NULL, "break-on-nr-mac", "stop tag interaction on nr-mac"), arg_lit0(NULL, "break", "stop tag interaction on nr-mac"),
arg_lit0("p", "prevent-epurse-update", "fake epurse update"), arg_lit0("p", "prevent", "fake epurse update"),
arg_lit0(NULL, "shallow", "shallow mod"), arg_lit0(NULL, "shallow", "shallow mod"),
arg_strx0("d", "data", "<hex>", "DER encoded command to send to SAM"), arg_strx0("d", "data", "<hex>", "DER encoded command to send to SAM"),
arg_param_end arg_param_end
@ -5871,19 +5886,33 @@ static int CmdHFiClassSAM(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 1);
bool disconnectAfter = !arg_get_lit(ctx, 2); bool disconnect_after = !arg_get_lit(ctx, 2);
bool skipDetect = arg_get_lit(ctx, 3); bool skip_detect = arg_get_lit(ctx, 3);
bool decodeTLV = arg_get_lit(ctx, 4); bool decodeTLV = arg_get_lit(ctx, 4);
bool breakOnNrMac = arg_get_lit(ctx, 5); bool break_nrmac = arg_get_lit(ctx, 5);
bool preventEpurseUpdate = arg_get_lit(ctx, 6); bool prevent = arg_get_lit(ctx, 6);
bool shallow_mod = arg_get_lit(ctx, 7); bool shallow_mod = arg_get_lit(ctx, 7);
uint8_t flags = 0; uint8_t flags = 0;
if (disconnectAfter) flags |= BITMASK(0); if (disconnect_after) {
if (skipDetect) flags |= BITMASK(1); flags |= BITMASK(0);
if (breakOnNrMac) flags |= BITMASK(2); }
if (preventEpurseUpdate) flags |= BITMASK(3);
if (shallow_mod) flags |= BITMASK(4); if (skip_detect) {
flags |= BITMASK(1);
}
if (break_nrmac) {
flags |= BITMASK(2);
}
if (prevent) {
flags |= BITMASK(3);
}
if (shallow_mod) {
flags |= BITMASK(4);
}
uint8_t data[PM3_CMD_DATA_SIZE] = {0}; uint8_t data[PM3_CMD_DATA_SIZE] = {0};
data[0] = flags; data[0] = flags;
@ -5954,20 +5983,21 @@ static int CmdHFiClassSAM(const char *Cmd) {
const uint8_t *oid = pacs + 2 + pacs_length; const uint8_t *oid = pacs + 2 + pacs_length;
const uint8_t oid_length = oid[1]; const uint8_t oid_length = oid[1];
const uint8_t *oid_data = oid + 2; const uint8_t *oid_data = oid + 2;
PrintAndLogEx(SUCCESS, "SIO OID.......: " _GREEN_("%s"), sprint_hex_inrow(oid_data, oid_length)); PrintAndLogEx(SUCCESS, "SIO OID.......... " _GREEN_("%s"), sprint_hex_inrow(oid_data, oid_length));
const uint8_t *mediaType = oid + 2 + oid_length; const uint8_t *mediaType = oid + 2 + oid_length;
const uint8_t mediaType_data = mediaType[2]; const uint8_t mediaType_data = mediaType[2];
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data)); PrintAndLogEx(SUCCESS, "SIO Media Type... " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
} else if (breakOnNrMac && d[0] == 0x05) { } else if (break_nrmac && d[0] == 0x05) {
PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d + 1, 8)); PrintAndLogEx(SUCCESS, "Nr-MAC........... " _GREEN_("%s"), sprint_hex_inrow(d + 1, 8));
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "Replay Nr-MAC to dump SIO:"); PrintAndLogEx(INFO, "Replay Nr-MAC to dump SIO:");
PrintAndLogEx(SUCCESS, " hf iclass dump -k \"%s\" --nr", sprint_hex_inrow(d + 1, 8)); PrintAndLogEx(SUCCESS, " hf iclass dump --nr -k %s", sprint_hex_inrow(d + 1, 8));
} }
} else { } else {
print_hex(d, resp.length); print_hex(d, resp.length);
} }
if (decodeTLV) { if (decodeTLV) {
asn1_print(d, d[1] + 2, " "); asn1_print(d, d[1] + 2, " ");
} }
@ -5990,7 +6020,7 @@ static command_t CommandTable[] = {
{"view", CmdHFiClassView, AlwaysAvailable, "Display content from tag dump file"}, {"view", CmdHFiClassView, AlwaysAvailable, "Display content from tag dump file"},
{"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "Write Picopass / iCLASS block"}, {"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "Write Picopass / iCLASS block"},
{"creditepurse", CmdHFiClassCreditEpurse, IfPm3Iclass, "Credit epurse value"}, {"creditepurse", CmdHFiClassCreditEpurse, IfPm3Iclass, "Credit epurse value"},
{"tear", CmdHFiClass_TearBlock, IfPm3Iclass, "Performs tearoff attack on iClass block"}, {"tear", CmdHFiClass_TearBlock, IfPm3Iclass, "Performs tearoff attack on iCLASS block"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("Recovery") " --------------------"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("Recovery") " --------------------"},
// {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "Automatic key recovery tool for iCLASS"}, // {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "Automatic key recovery tool for iCLASS"},
{"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "Check keys"}, {"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "Check keys"},

View file

@ -3244,7 +3244,7 @@
}, },
"hf iclass chk": { "hf iclass chk": {
"command": "hf iclass chk", "command": "hf iclass chk",
"description": "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag", "description": "Checkkeys loads a dictionary text file with 8 byte hex keys to test authenticating against a iCLASS tag",
"notes": [ "notes": [
"hf iclass chk -f iclass_default_keys.dic", "hf iclass chk -f iclass_default_keys.dic",
"hf iclass chk -f iclass_elite_keys.dic --elite", "hf iclass chk -f iclass_elite_keys.dic --elite",
@ -3367,13 +3367,12 @@
}, },
"hf iclass encode": { "hf iclass encode": {
"command": "hf iclass encode", "command": "hf iclass encode",
"description": "Encode binary wiegand to block 7,8,9 Use either --bin or --wiegand/--fc/--cn", "description": "Encode binary wiegand to block 7,8,9 Use either --bin or --wiegand/--fc/--cn When using emulator you have to first load a credential into emulator memory",
"notes": [ "notes": [
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)", "hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)",
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)", "hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key", "hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key",
"hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory", "hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory"
"When using emulator you have to first load a credential into emulator memory"
], ],
"offline": true, "offline": true,
"options": [ "options": [
@ -3511,7 +3510,7 @@
}, },
"hf iclass legrec": { "hf iclass legrec": {
"command": "hf iclass legrec", "command": "hf iclass legrec",
"description": "Attempts to recover the diversified key of a specific iClass card. This may take several days. The card must remain be on the PM3 antenna during the whole process. ! Warning ! This process may brick the card! ! Warning !", "description": "Attempts to recover the diversified key of a specific iCLASS card. This may take several days. The card must remain be on the PM3 antenna during the whole process. ! Warning ! This process may brick the card! ! Warning !",
"notes": [ "notes": [
"hf iclass legrec --macs 0000000089cb984b", "hf iclass legrec --macs 0000000089cb984b",
"hf iclass legrec --macs 0000000089cb984b --index 0 --loop 100 --notest" "hf iclass legrec --macs 0000000089cb984b --index 0 --loop 100 --notest"
@ -3670,8 +3669,8 @@
"description": "Extract PACS via a HID SAM", "description": "Extract PACS via a HID SAM",
"notes": [ "notes": [
"hf iclass sam", "hf iclass sam",
"hf iclass sam -p -d a005a103800104 -> get PACS data, but ensure that epurse will stay unchanged", "hf iclass sam -p -d a005a103800104 -> get PACS data, prevent epurse update",
"hf iclass sam --break-on-nr-mac -> get Nr-MAC for extracting encrypted SIO" "hf iclass sam --break -> get Nr-MAC for extracting encrypted SIO"
], ],
"offline": false, "offline": false,
"options": [ "options": [
@ -3680,12 +3679,12 @@
"-k, --keep keep the field active after command executed", "-k, --keep keep the field active after command executed",
"-n, --nodetect skip selecting the card and sending card details to SAM", "-n, --nodetect skip selecting the card and sending card details to SAM",
"-t, --tlv decode TLV", "-t, --tlv decode TLV",
"--break-on-nr-mac stop tag interaction on nr-mac", "--break stop tag interaction on nr-mac",
"-p, --prevent-epurse-update fake epurse update", "-p, --prevent fake epurse update",
"--shallow shallow mod", "--shallow shallow mod",
"-d, --data <hex> DER encoded command to send to SAM" "-d, --data <hex> DER encoded command to send to SAM"
], ],
"usage": "hf iclass sam [-hvkntp] [--break-on-nr-mac] [--shallow] [-d <hex>]..." "usage": "hf iclass sam [-hvkntp] [--break] [--shallow] [-d <hex>]..."
}, },
"hf iclass sim": { "hf iclass sim": {
"command": "hf iclass sim", "command": "hf iclass sim",
@ -13375,6 +13374,6 @@
"metadata": { "metadata": {
"commands_extracted": 768, "commands_extracted": 768,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2025-06-06T15:54:11" "extracted_on": "2025-06-06T16:58:34"
} }
} }

View file

@ -404,7 +404,7 @@ Check column "offline" for their availability.
|`hf iclass view `|Y |`Display content from tag dump file` |`hf iclass view `|Y |`Display content from tag dump file`
|`hf iclass wrbl `|N |`Write Picopass / iCLASS block` |`hf iclass wrbl `|N |`Write Picopass / iCLASS block`
|`hf iclass creditepurse `|N |`Credit epurse value` |`hf iclass creditepurse `|N |`Credit epurse value`
|`hf iclass tear `|N |`Performs tearoff attack on iClass block` |`hf iclass tear `|N |`Performs tearoff attack on iCLASS block`
|`hf iclass chk `|N |`Check keys` |`hf iclass chk `|N |`Check keys`
|`hf iclass loclass `|Y |`Use loclass to perform bruteforce reader attack` |`hf iclass loclass `|Y |`Use loclass to perform bruteforce reader attack`
|`hf iclass lookup `|Y |`Uses authentication trace to check for key in dictionary file` |`hf iclass lookup `|Y |`Uses authentication trace to check for key in dictionary file`