Merge branch 'master' into allin

update 201129
This commit is contained in:
tharexde 2020-11-29 00:22:09 +01:00
commit 72b21f018e
20 changed files with 1235 additions and 577 deletions

View file

@ -7,6 +7,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001)
- Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...)
- ...
- Change `hf iclass chk/lookup/loclass` speedups (@iceman1001)
- Change - ongoing convertion to cliparser (@tcprst, @iceman1001)
- Added compilation options for 256k Proxmark versions, see doc (@doegox)
- Added support for 10b UID in `hf 14a sim` (@doegox)
- Added `HF_TCPRST` standalone mode which read and emulate IKEA Rothult cards (@tcprst)

View file

@ -169,6 +169,7 @@ help:
@echo "+ fpga_compress - Make tools/fpga_compress"
@echo
@echo "+ style - Apply some automated source code formatting rules"
@echo "+ cliparser - Generate cliparser TODO
@echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script"
@echo "+ .../check - Run offline tests against specific target. See above."
@echo "+ miscchecks - Detect various encoding issues in source code"
@ -248,6 +249,14 @@ endif
# easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*)
cliparser:
# Get list of all commands
cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v help | awk '{$$1=$$1};1' > cliparser_all_commands.tmp
# Get list of cliparserized commands
grep -r CLIParserInit ./client/src/ | cut -f 2 -d "\"" | awk '{$$1=$$1};1' > cliparser_done.tmp
# Determine commands that still need cliparser conversion
grep -xvf cliparser_done.tmp cliparser_all_commands.tmp > ./doc/cliparser_todo.txt
style:
# Make sure astyle is installed
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )

View file

@ -620,7 +620,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
set_tracelen(numbts);
set_tracelen(BigBuf_max_traceLen());
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
Dbprintf("Felica sniffing done, tracelen: %i, use " _YELLOW_("`hf felica list`") " for annotations", BigBuf_get_traceLen());
reply_mix(CMD_ACK, 1, numbts, 0, 0, 0);
LED_D_OFF();
}

View file

@ -20,6 +20,7 @@
#include "ticks.h"
#include "dbprint.h"
#include "util.h"
#include "util.h"
#include "parity.h"
#include "mifareutil.h"
#include "commonutil.h"
@ -1979,9 +1980,11 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
for (;;) {
WDT_HIT();
if (check == 2000) {
if (BUTTON_PRESS())
if (check == 1000) {
if (BUTTON_PRESS() || data_available()) {
Dbprintf("----------- " _GREEN_("BREAKING") " ----------");
return 1;
}
check = 0;
}
++check;

View file

@ -535,8 +535,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
WDT_HIT();
if (counter == 2000) {
if (counter == 1000) {
if (data_available()) {
Dbprintf("----------- " _GREEN_("BREAKING") " ----------");
break;
}
counter = 0;

View file

@ -105,6 +105,11 @@ c934fe34d934
cccccccccccc
dddddddddddd
eeeeeeeeeeee
#
# elevator
# data from forum
FFFFFF545846
#
f1a97341a9fc
44ab09010845 # hotel system
85fed980ea5a # hotel system

View file

@ -20,6 +20,11 @@ A5B4C3D2
00434343
44B44CAE
88661858
#
# ZX-copy3 T55xx / EM4305
# ref. http://www.proxmark.org/forum/viewtopic.php?pid=40662#p40662
19920427
84AC15E2
# paxton bullit?
575F4F4B
#

View file

@ -49,7 +49,7 @@ static int usage_hf_felica_sim(void) {
static int usage_hf_felica_sniff(void) {
PrintAndLogEx(NORMAL, "\nInfo: It get data from the field and saves it into command buffer. ");
PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf list felica'");
PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf felica list'");
PrintAndLogEx(NORMAL, "\nUsage: hf felica sniff [-h] [-s] [-t]");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -s samples to skip (decimal) max 9999");

File diff suppressed because it is too large Load diff

View file

@ -154,7 +154,7 @@ static int CmdSecurakeyClone(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
arg_str1("r", "raw", "<hex>", "raw hex data. 12 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

@ -207,7 +207,7 @@ static int CmdVisa2kClone(const char *Cmd) {
blocks[2] = id;
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu32, cardtype, id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: " _GREEN_("%"PRIu32), cardtype, id);
print_blocks(blocks, ARRAYLEN(blocks));
int res;

View file

@ -39,13 +39,14 @@
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include "cipherutils.h"
#include "cipher.h"
#include "ikeys.h"
#include "elite_crack.h"
#include "fileutils.h"
#include "des.h"
#include "mbedtls/des.h"
#include "util_posix.h"
/**
@ -70,8 +71,7 @@
* @param dest
*/
void permutekey(uint8_t key[8], uint8_t dest[8]) {
int i;
for (i = 0 ; i < 8 ; i++) {
for (uint8_t i = 0 ; i < 8 ; i++) {
dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
(((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
(((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
@ -164,12 +164,16 @@ rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
**/
static void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
memcpy(outp_key, key, 8);
uint8_t j;
while (n-- > 0) {
for (j = 0; j < 8 ; j++)
outp_key[j] = rl(outp_key[j]);
outp_key[0] = rl(outp_key[0]);
outp_key[1] = rl(outp_key[1]);
outp_key[2] = rl(outp_key[2]);
outp_key[3] = rl(outp_key[3]);
outp_key[4] = rl(outp_key[4]);
outp_key[5] = rl(outp_key[5]);
outp_key[6] = rl(outp_key[6]);
outp_key[7] = rl(outp_key[7]);
}
return;
}
static mbedtls_des_context ctx_enc;
@ -214,16 +218,22 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
uint8_t z[8][8] = {{0}, {0}};
uint8_t temp_output[8] = {0};
//calculate complement of key
int i;
for (i = 0; i < 8; i++)
key64_negated[i] = ~key64[i];
key64_negated[0] = ~key64[0];
key64_negated[1] = ~key64[1];
key64_negated[2] = ~key64[2];
key64_negated[3] = ~key64[3];
key64_negated[4] = ~key64[4];
key64_negated[5] = ~key64[5];
key64_negated[6] = ~key64[6];
key64_negated[7] = ~key64[7];
// Once again, key is on iclass-format
desencrypt_iclass(key64, key64_negated, z[0]);
// PrintAndLogEx(NORMAL, "");
// PrintAndLogEx(INFO, "High security custom key (Kcus):");
// PrintAndLogEx(INFO, "z0 %s", sprint_hex(z[0],8));
if (g_debugMode > 0) {
PrintAndLogEx(DEBUG, "High security custom key (Kcus):");
PrintAndLogEx(DEBUG, "z0 %s", sprint_hex(z[0],8));
}
uint8_t y[8][8] = {{0}, {0}};
@ -232,7 +242,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
desdecrypt_iclass(z[0], key64_negated, y[0]);
// PrintAndLogEx(INFO, "y0 %s", sprint_hex(y[0],8));
for (i = 1; i < 8; i++) {
for (uint8_t i = 1; i < 8; i++) {
// z [i] = DES dec (rk(K cus , i), z [i1] )
rk(key64, i, temp_output);
//y [i] = DES enc (rk(K cus , i), y [i1] )
@ -242,7 +252,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
}
if (outp_keytable != NULL) {
for (i = 0 ; i < 8 ; i++) {
for (uint8_t i = 0 ; i < 8 ; i++) {
memcpy(outp_keytable + i * 16, y[i], 8);
memcpy(outp_keytable + 8 + i * 16, z[i], 8);
}
@ -280,25 +290,121 @@ static int _readFromDump(uint8_t dump[], dumpdata *item, uint8_t i) {
return 0;
}
*/
//static uint32_t startvalue = 0;
/**
* @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.
*This method calculates the hash1 for the CSN, and determines what bytes need to be bruteforced
*on the fly. If it finds that more than three bytes need to be bruteforced, it aborts.
*It updates the keytable with the findings, also using the upper half of the 16-bit ints
*to signal if the particular byte has been cracked or not.
*
* @param dump The dumpdata from iclass reader attack.
* @param keytable where to write found values.
* @return
*/
int bruteforceItem(dumpdata item, uint16_t keytable[]) {
int found = false;
uint8_t key_sel_p[8] = {0};
uint8_t div_key[8] = {0};
uint8_t key_sel[8] = {0};
uint8_t calculated_MAC[4] = {0};
typedef struct {
int thread_idx;
uint32_t endmask;
uint8_t numbytes_to_recover;
uint8_t bytes_to_recover[3];
uint8_t key_index[8];
uint16_t keytable[128];
loclass_dumpdata_t item;
} loclass_thread_arg_t;
typedef struct {
uint8_t values[3];
} loclass_thread_ret_t;
static size_t loclass_tc = 1;
static int loclass_found = 0;
static void* bf_thread(void* thread_arg) {
loclass_thread_arg_t *targ = (loclass_thread_arg_t *)thread_arg;
const uint32_t endmask = targ->endmask;
const uint8_t numbytes_to_recover = targ->numbytes_to_recover;
uint32_t brute = targ->thread_idx;
uint8_t csn[8];
uint8_t cc_nr[12];
uint8_t mac[4];
uint8_t key_index[8];
uint8_t bytes_to_recover[3];
uint16_t keytable[128];
memcpy(csn, targ->item.csn, sizeof(csn));
memcpy(cc_nr, targ->item.cc_nr, sizeof(cc_nr));
memcpy(mac, targ->item.mac, sizeof(mac));
memcpy(key_index, targ->key_index, sizeof(key_index));
memcpy(bytes_to_recover, targ->bytes_to_recover, sizeof(bytes_to_recover));
memcpy(keytable, targ->keytable, sizeof(keytable));
int found;
while (!(brute & endmask)) {
found = __atomic_load_n (&loclass_found, __ATOMIC_SEQ_CST);
if (found != 0xFF) return NULL;
//Update the keytable with the brute-values
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF00;
keytable[bytes_to_recover[i]] |= (brute >> (i * 8) & 0xFF);
}
uint8_t key_sel[8] = {0};
// Piece together the key
key_sel[0] = keytable[key_index[0]] & 0xFF;
key_sel[1] = keytable[key_index[1]] & 0xFF;
key_sel[2] = keytable[key_index[2]] & 0xFF;
key_sel[3] = keytable[key_index[3]] & 0xFF;
key_sel[4] = keytable[key_index[4]] & 0xFF;
key_sel[5] = keytable[key_index[5]] & 0xFF;
key_sel[6] = keytable[key_index[6]] & 0xFF;
key_sel[7] = keytable[key_index[7]] & 0xFF;
// Permute from iclass format to standard format
uint8_t key_sel_p[8] = {0};
permutekey_rev(key_sel, key_sel_p);
// Diversify
uint8_t div_key[8] = {0};
diversifyKey(csn, key_sel_p, div_key);
// Calc mac
uint8_t calculated_MAC[4] = {0};
doMAC(cc_nr, div_key, calculated_MAC);
// success
if (memcmp(calculated_MAC, mac, 4) == 0) {
loclass_thread_ret_t *r = (loclass_thread_ret_t*)malloc(sizeof(loclass_thread_ret_t));
for (uint8_t i = 0 ; i < numbytes_to_recover; i++) {
r->values[i] = keytable[bytes_to_recover[i]] & 0xFF;
}
__atomic_store_n(&loclass_found, targ->thread_idx, __ATOMIC_SEQ_CST);
pthread_exit ((void*)r);
}
brute += loclass_tc;
#define _CLR_ "\x1b[0K"
if (numbytes_to_recover == 3) {
if ((brute > 0) && ((brute & 0xFFFF) == 0)) {
PrintAndLogEx(INPLACE, "[ %02x %02x %02x ] %8u / %u", bytes_to_recover[0], bytes_to_recover[1], bytes_to_recover[2] , brute, 0xFFFFFF);
}
} else if (numbytes_to_recover == 2) {
if ((brute > 0) && ((brute & 0x3F) == 0))
PrintAndLogEx(INPLACE, "[ %02x %02x ] %5u / %u" _CLR_ , bytes_to_recover[0], bytes_to_recover[1], brute, 0xFFFF);
} else {
if ((brute > 0) && ((brute & 0x1F) == 0))
PrintAndLogEx(INPLACE, "[ %02x ] %3u / %u" _CLR_, bytes_to_recover[0], brute, 0xFF);
}
}
pthread_exit(NULL);
void* dummyptr = NULL;
return dummyptr;
}
int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) {
// reset thread signals
loclass_found = 0xFF;
//Get the key index (hash1)
uint8_t key_index[8] = {0};
@ -317,13 +423,12 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
* Only the lower eight bits correspond to the (hopefully cracked) key-value.
**/
uint8_t bytes_to_recover[3] = {0};
uint8_t numbytes_to_recover = 0 ;
int i;
for (i = 0; i < 8; i++) {
if (keytable[key_index[i]] & (CRACKED | BEING_CRACKED)) continue;
uint8_t numbytes_to_recover = 0;
for (uint8_t i = 0; i < 8; i++) {
if (keytable[key_index[i]] & (LOCLASS_CRACKED | LOCLASS_BEING_CRACKED)) continue;
bytes_to_recover[numbytes_to_recover++] = key_index[i];
keytable[key_index[i]] |= BEING_CRACKED;
keytable[key_index[i]] |= LOCLASS_BEING_CRACKED;
if (numbytes_to_recover > 3) {
PrintAndLogEx(FAILED, "The CSN requires > 3 byte bruteforce, not supported");
@ -331,18 +436,141 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
PrintAndLogEx(INFO, "HASH1 %s", sprint_hex(key_index, 8));
PrintAndLogEx(NORMAL, "");
//Before we exit, reset the 'BEING_CRACKED' to zero
keytable[bytes_to_recover[0]] &= ~BEING_CRACKED;
keytable[bytes_to_recover[1]] &= ~BEING_CRACKED;
keytable[bytes_to_recover[2]] &= ~BEING_CRACKED;
keytable[bytes_to_recover[0]] &= ~LOCLASS_BEING_CRACKED;
keytable[bytes_to_recover[1]] &= ~LOCLASS_BEING_CRACKED;
keytable[bytes_to_recover[2]] &= ~LOCLASS_BEING_CRACKED;
return PM3_ESOFT;
}
}
if (numbytes_to_recover == 0) {
PrintAndLogEx(INFO, "No bytes to recover, exiting");
return PM3_ESOFT;
}
loclass_thread_arg_t args[loclass_tc];
// init thread arguments
for (int i = 0; i < loclass_tc; i++) {
args[i].thread_idx = i;
args[i].numbytes_to_recover = numbytes_to_recover;
args[i].endmask = 1 << 8 * numbytes_to_recover;
memcpy((void*)&args[i].item, (void*)&item, sizeof(loclass_dumpdata_t));
memcpy(args[i].bytes_to_recover, bytes_to_recover, sizeof(args[i].bytes_to_recover) );
memcpy(args[i].key_index, key_index, sizeof(args[i].key_index) );
memcpy(args[i].keytable, keytable, sizeof(args[i].keytable));
}
pthread_t threads[loclass_tc];
// create threads
for (int i = 0; i < loclass_tc; i++) {
int res = pthread_create(&threads[i], NULL, bf_thread, (void *)&args[i]);
if (res) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "Failed to create pthreads. Quitting");
return PM3_ESOFT;
}
}
// wait for threads to terminate:
void* ptrs[loclass_tc];
for (int i = 0; i < loclass_tc; i++)
pthread_join(threads[i], &ptrs[i]);
// was it a success?
int res = PM3_SUCCESS;
if (loclass_found == 0xFF) {
res = PM3_ESOFT;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8));
//Before we exit, reset the 'BEING_CRACKED' to zero
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= LOCLASS_CRACK_FAILED;
}
} else {
loclass_thread_ret_t ice = *((loclass_thread_ret_t *)ptrs[loclass_found]);
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] = ice.values[i];
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= LOCLASS_CRACKED;
}
for (uint8_t i = 0; i < loclass_tc; i++) {
free(ptrs[i]);
}
}
memset(args, 0x00, sizeof(args));
memset(threads, 0x00, sizeof(threads));
return res;
}
/**
* @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.
*This method calculates the hash1 for the CSN, and determines what bytes need to be bruteforced
*on the fly. If it finds that more than three bytes need to be bruteforced, it aborts.
*It updates the keytable with the findings, also using the upper half of the 16-bit ints
*to signal if the particular byte has been cracked or not.
*
* @param dump The dumpdata from iclass reader attack.
* @param keytable where to write found values.
* @return
*/
/*
int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]) {
//Get the key index (hash1)
uint8_t key_index[8] = {0};
hash1(item.csn, key_index);
*/
/*
*A uint32 has room for 4 bytes, we'll only need 24 of those bits to bruteforce up to three bytes,
*/
//uint32_t brute = startvalue;
* Determine which bytes to retrieve. A hash is typically
* 01010000454501
* We go through that hash, and in the corresponding keytable, we put markers
* on what state that particular index is:
* - CRACKED (this has already been cracked)
* - BEING_CRACKED (this is being bruteforced now)
* - CRACK_FAILED (self-explaining...)
*
* The markers are placed in the high area of the 16 bit key-table.
* Only the lower eight bits correspond to the (hopefully cracked) key-value.
**/
/*
uint8_t bytes_to_recover[3] = {0};
uint8_t numbytes_to_recover = 0 ;
for (uint8_t i = 0; i < 8; i++) {
if (keytable[key_index[i]] & (LOCLASS_CRACKED | LOCLASS_BEING_CRACKED)) continue;
bytes_to_recover[numbytes_to_recover++] = key_index[i];
keytable[key_index[i]] |= LOCLASS_BEING_CRACKED;
if (numbytes_to_recover > 3) {
PrintAndLogEx(FAILED, "The CSN requires > 3 byte bruteforce, not supported");
PrintAndLogEx(INFO, "CSN %s", sprint_hex(item.csn, 8));
PrintAndLogEx(INFO, "HASH1 %s", sprint_hex(key_index, 8));
PrintAndLogEx(NORMAL, "");
//Before we exit, reset the 'BEING_CRACKED' to zero
keytable[bytes_to_recover[0]] &= ~LOCLASS_BEING_CRACKED;
keytable[bytes_to_recover[1]] &= ~LOCLASS_BEING_CRACKED;
keytable[bytes_to_recover[2]] &= ~LOCLASS_BEING_CRACKED;
return PM3_ESOFT;
}
}
uint8_t key_sel_p[8] = {0};
uint8_t div_key[8] = {0};
uint8_t key_sel[8] = {0};
uint8_t calculated_MAC[4] = {0};
//A uint32 has room for 4 bytes, we'll only need 24 of those bits to bruteforce up to three bytes,
uint32_t brute = 0;
*/
/*
Determine where to stop the bruteforce. A 1-byte attack stops after 256 tries,
(when brute reaches 0x100). And so on...
@ -350,16 +578,17 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
bytes_to_recover = 2 --> endmask = 0x000010000
bytes_to_recover = 3 --> endmask = 0x001000000
*/
/*
uint32_t endmask = 1 << 8 * numbytes_to_recover;
PrintAndLogEx(NORMAL, "----------------------------");
for (i = 0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++)
PrintAndLogEx(INFO, "Bruteforcing byte %d", bytes_to_recover[i]);
for (uint8_t i = 0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++)
PrintAndLogEx(INFO, "Bruteforcing %d", bytes_to_recover[i]);
bool found = false;
while (!found && !(brute & endmask)) {
//Update the keytable with the brute-values
for (i = 0; i < numbytes_to_recover; i++) {
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF00;
keytable[bytes_to_recover[i]] |= (brute >> (i * 8) & 0xFF);
}
@ -376,16 +605,15 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
//Permute from iclass format to standard format
permutekey_rev(key_sel, key_sel_p);
//Diversify
diversifyKey(item.csn, key_sel_p, div_key);
//Calc mac
doMAC(item.cc_nr, div_key, calculated_MAC);
// success
if (memcmp(calculated_MAC, item.mac, 4) == 0) {
PrintAndLogEx(NORMAL, "");
for (i = 0 ; i < numbytes_to_recover; i++) {
PrintAndLogEx(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]);
for (uint8_t i = 0 ; i < numbytes_to_recover; i++) {
PrintAndLogEx(SUCCESS, "%d: 0x%02x", bytes_to_recover[i], keytable[bytes_to_recover[i]] & 0xFF);
}
found = true;
break;
@ -393,9 +621,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
brute++;
if ((brute & 0xFFFF) == 0) {
PrintAndLogEx(NORMAL, "%3d," NOLF, (brute >> 16) & 0xFF);
if (((brute >> 16) % 0x10) == 0)
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INPLACE, "%3d", (brute >> 16) & 0xFF);
}
}
@ -408,19 +634,20 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
errors = PM3_ESOFT;
//Before we exit, reset the 'BEING_CRACKED' to zero
for (i = 0; i < numbytes_to_recover; i++) {
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= CRACK_FAILED;
keytable[bytes_to_recover[i]] |= LOCLASS_CRACK_FAILED;
}
} else {
//PrintAndLogEx(SUCCESS, "DES calcs: %u", brute);
for (i = 0; i < numbytes_to_recover; i++) {
for (uint8_t i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= CRACKED;
keytable[bytes_to_recover[i]] |= LOCLASS_CRACKED;
}
}
return errors;
}
*/
/**
* From dismantling iclass-paper:
@ -434,7 +661,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
* @param master_key where to put the master key
* @return 0 for ok, 1 for failz
*/
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) {
int calculateMasterKey(uint8_t first16bytes[], uint8_t kcus[]) {
mbedtls_des_context ctx_e;
uint8_t z_0[8] = {0};
@ -457,9 +684,14 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) {
mbedtls_des_setkey_enc(&ctx_e, z_0_rev);
mbedtls_des_crypt_ecb(&ctx_e, y_0, key64_negated);
int i;
for (i = 0; i < 8 ; i++)
key64[i] = ~key64_negated[i];
key64[0] = ~key64_negated[0];
key64[1] = ~key64_negated[1];
key64[2] = ~key64_negated[2];
key64[3] = ~key64_negated[3];
key64[4] = ~key64_negated[4];
key64[5] = ~key64_negated[5];
key64[6] = ~key64_negated[6];
key64[7] = ~key64_negated[7];
// Can we verify that the key is correct?
// Once again, key is on iclass-format
@ -468,21 +700,20 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) {
mbedtls_des_setkey_enc(&ctx_e, key64_stdformat);
mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "-- High security custom key (Kcus) --");
PrintAndLogEx(SUCCESS, "Standard format " _GREEN_("%s"), sprint_hex(key64_stdformat, 8));
PrintAndLogEx(SUCCESS, "iClass format %s", sprint_hex(key64, 8));
if (master_key != NULL)
memcpy(master_key, key64, 8);
if (kcus != NULL)
memcpy(kcus, key64, 8);
PrintAndLogEx(NORMAL, "\n");
if (memcmp(z_0, result, 4) != 0) {
PrintAndLogEx(WARNING, _RED_("Failed to verify") " calculated master key (k_cus)! Something is wrong.");
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, _GREEN_("Key verified ok!"));
PrintAndLogEx(SUCCESS, "----- " _CYAN_("High security custom key (Kcus)") " -----");
PrintAndLogEx(SUCCESS, "Standard format %s", sprint_hex(key64_stdformat, 8));
PrintAndLogEx(SUCCESS, "iCLASS format " _GREEN_("%s"), sprint_hex(key64, 8));
PrintAndLogEx(SUCCESS, "Key verified (" _GREEN_("ok") ")");
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
/**
@ -494,28 +725,32 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) {
*/
int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) {
uint8_t i;
size_t itemsize = sizeof(dumpdata);
uint64_t t1 = msclock();
dumpdata *attack = (dumpdata *) calloc(itemsize, sizeof(uint8_t));
size_t itemsize = sizeof(loclass_dumpdata_t);
loclass_dumpdata_t *attack = (loclass_dumpdata_t *) calloc(itemsize, sizeof(uint8_t));
if (attack == NULL) {
PrintAndLogEx(WARNING, "failed to allocate memory");
return PM3_EMALLOC;
}
loclass_tc = num_CPUs();
PrintAndLogEx(INFO, "bruteforce using " _YELLOW_("%zu") " threads", loclass_tc);
int res = 0;
uint64_t t1 = msclock();
for (i = 0 ; i * itemsize < dumpsize ; i++) {
memcpy(attack, dump + i * itemsize, itemsize);
res += bruteforceItem(*attack, keytable);
res = bruteforceItem(*attack, keytable);
if (res != PM3_SUCCESS)
break;
}
free(attack);
t1 = msclock() - t1;
PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds", t1 / 1000);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "time " _YELLOW_("%" PRIu64) " seconds", t1 / 1000);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "loclass exiting. Try run " _YELLOW_("`hf iclass sim 2`") " again and collect new data");
PrintAndLogEx(ERR, "loclass exiting. Try run " _YELLOW_("`hf iclass sim -t 2`") " again and collect new data");
return PM3_ESOFT;
}
@ -524,11 +759,10 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) {
// indicate crack-status. Those must be discarded for the
// master key calculation
uint8_t first16bytes[16] = {0};
for (i = 0 ; i < 16 ; i++) {
first16bytes[i] = keytable[i] & 0xFF;
if (!(keytable[i] & CRACKED)) {
if ((keytable[i] & LOCLASS_CRACKED) != LOCLASS_CRACKED) {
PrintAndLogEx(WARNING, "Warning: we are missing byte %d, custom key calculation will fail...", i);
return PM3_ESOFT;
}
@ -620,7 +854,7 @@ static int _test_iclass_key_permutation(void) {
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Iclass key permutation (%s)", _GREEN_("OK"));
PrintAndLogEx(SUCCESS, " Iclass key permutation (%s)", _GREEN_("ok"));
return PM3_SUCCESS;
}
@ -640,8 +874,8 @@ static int _testHash1(void) {
}
int testElite(bool slowtests) {
PrintAndLogEx(INFO, "Testing iClass Elite functinality...");
PrintAndLogEx(INFO, "Testing hash2");
PrintAndLogEx(INFO, "Testing iClass Elite functionality");
PrintAndLogEx(INFO, "Testing hash2...");
uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39};
/**
@ -661,20 +895,19 @@ int testElite(bool slowtests) {
*/
uint8_t keytable[128] = {0};
hash2(k_cus, keytable);
printarr_human_readable("Hash2", keytable, 128);
printarr_human_readable("---------------------- Hash2 ----------------------", keytable, sizeof(keytable));
if (keytable[3] == 0xA1 && keytable[0x30] == 0xA3 && keytable[0x6F] == 0x95) {
PrintAndLogEx(SUCCESS, " Hash2 (%s)", _GREEN_("ok"));
PrintAndLogEx(SUCCESS, " hash2 (%s)", _GREEN_("ok"));
}
int res = PM3_SUCCESS;
PrintAndLogEx(INFO, "Testing hash1...");
res += _testHash1();
PrintAndLogEx(INFO, " hash1 (%s)", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " hash1 (%s)", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail") );
PrintAndLogEx(INFO, "Testing key diversification...");
res += _test_iclass_key_permutation();
if (res == PM3_SUCCESS)
PrintAndLogEx(INFO, " key diversification (%s)", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx((res == PM3_SUCCESS) ? SUCCESS : WARNING, " key diversification (%s)", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail") );
if (slowtests)
res += _testBruteforce();

View file

@ -38,6 +38,22 @@
#ifndef ELITE_CRACK_H
#define ELITE_CRACK_H
//Crack status, see below
#define LOCLASS_CRACKED 0x0100
#define LOCLASS_BEING_CRACKED 0x0200
#define LOCLASS_CRACK_FAILED 0x0400
/**
This is how we expect each 'entry' in a dumpfile to look
**/
typedef struct {
uint8_t csn[8];
uint8_t cc_nr[12];
uint8_t mac[4];
} loclass_dumpdata_t;
void permutekey(uint8_t key[8], uint8_t dest[8]);
/**
* Permutes a key from iclass specific format to NIST format
@ -46,10 +62,6 @@ void permutekey(uint8_t key[8], uint8_t dest[8]);
* @param dest
*/
void permutekey_rev(uint8_t key[8], uint8_t dest[8]);
//Crack status, see below
#define CRACKED 0x0100
#define BEING_CRACKED 0x0200
#define CRACK_FAILED 0x0400
/**
* Perform a bruteforce against a file which has been saved by pm3
@ -69,7 +81,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]);
*/
int bruteforceFileNoKeys(const char *filename);
/**
* @brief Same as bruteforcefile, but uses a an array of dumpdata instead
* @brief Same as bruteforcefile, but uses a an array of loclass_dumpdata_t instead
* @param dump
* @param dumpsize
* @param keytable
@ -77,15 +89,6 @@ int bruteforceFileNoKeys(const char *filename);
*/
int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]);
/**
This is how we expect each 'entry' in a dumpfile to look
**/
typedef struct {
uint8_t csn[8];
uint8_t cc_nr[12];
uint8_t mac[4];
} dumpdata;
/**
* @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.
*This method calculates the hash1 for the CSN, and determines what bytes need to be bruteforced
@ -93,11 +96,11 @@ typedef struct {
*It updates the keytable with the findings, also using the upper half of the 16-bit ints
*to signal if the particular byte has been cracked or not.
*
* @param dump The dumpdata from iclass reader attack.
* @param loclass_dumpdata_t The dumpdata from iclass reader attack.
* @param keytable where to write found values.
* @return
*/
int bruteforceItem(dumpdata item, uint16_t keytable[]);
int bruteforceItem(loclass_dumpdata_t item, uint16_t keytable[]);
/**
* Hash1 takes CSN as input, and determines what bytes in the keytable will be used
* when constructing the K_sel.
@ -118,7 +121,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable);
* @param master_key where to put the master key
* @return 0 for ok, 1 for failz
*/
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]);
int calculateMasterKey(uint8_t first16bytes[], uint8_t master_key[]);
/**
* @brief Test function
@ -141,5 +144,4 @@ int testElite(bool slowtests);
**/
#endif

View file

@ -70,7 +70,7 @@ From "Dismantling iclass":
#include "fileutils.h"
#include "cipherutils.h"
#include "des.h"
#include "mbedtls/des.h"
uint8_t pi[35] = {
0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D,
@ -80,9 +80,6 @@ uint8_t pi[35] = {
0x72, 0x74, 0x78
};
static mbedtls_des_context ctx_enc;
static mbedtls_des_context ctx_dec;
/**
* @brief The key diversification algorithm uses 6-bit bytes.
* This implementation uses 64 bit uint to pack seven of them into one
@ -94,16 +91,19 @@ static mbedtls_des_context ctx_dec;
* @param n bitnumber
* @return
*/
static uint8_t getSixBitByte(uint64_t c, int n) {
#define getSixBitByte(c, n) ((uint8_t)(((c) >> (42 - 6 * (n))) & 0x3F))
/*
static inline uint8_t getSixBitByte(uint64_t c, int n) {
return (c >> (42 - 6 * n)) & 0x3F;
}
*/
/**
* @brief Puts back a six-bit 'byte' into a uint64_t.
* @param c buffer
* @param z the value to place there
* @param n bitnumber.
*/
static void pushbackSixBitByte(uint64_t *c, uint8_t z, int n) {
//0x XXXX YYYY ZZZZ ZZZZ ZZZZ
// ^z0 ^z7
@ -210,14 +210,14 @@ static void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *o
return;
bool pn = tailBit(p_in);
if (pn) { // pn = 1
if (pn) {
// pn = 1
uint8_t zl = getSixBitByte(z, l);
push6bits(out, zl + 1);
permute(p_in, z, l + 1, r, out);
} else { // otherwise
} else {
// otherwise
uint8_t zr = getSixBitByte(z, r);
push6bits(out, zr);
permute(p_in, z, l, r + 1, out);
}
@ -226,6 +226,7 @@ static void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *o
static void printState(const char *desc, uint64_t c) {
if (g_debugMode == 0)
return;
char s[60] = {0};
snprintf(s, sizeof(s), "%s : ", desc);
@ -254,8 +255,10 @@ static void printState(const char *desc, uint64_t c) {
void hash0(uint64_t c, uint8_t k[8]) {
c = swapZvalues(c);
if (g_debugMode > 0) {
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
printState("origin", c);
}
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
// x = 8 bits
// y = 8 bits
@ -266,9 +269,7 @@ void hash0(uint64_t c, uint8_t k[8]) {
for (int n = 0; n < 4 ; n++) {
uint8_t zn = getSixBitByte(c, n);
uint8_t zn4 = getSixBitByte(c, n + 4);
uint8_t _zn = (zn % (63 - n)) + n;
uint8_t _zn4 = (zn4 % (64 - n)) + n;
@ -276,17 +277,18 @@ void hash0(uint64_t c, uint8_t k[8]) {
pushbackSixBitByte(&zP, _zn4, n + 4);
}
printState("0|0|z'", zP);
if (g_debugMode > 0) printState("0|0|z'", zP);
uint64_t zCaret = check(zP);
printState("0|0|z^", zP);
if (g_debugMode > 0) printState("0|0|z^", zP);
uint8_t p = pi[x % 35];
if (x & 1) //Check if x7 is 1
p = ~p;
PrintAndLogEx(DEBUG, "p: %02x", p);
if (g_debugMode > 0) PrintAndLogEx(DEBUG, " p : %02x", p);
BitstreamIn p_in = { &p, 8, 0 };
uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0};
@ -301,9 +303,8 @@ void hash0(uint64_t c, uint8_t k[8]) {
zTilde >>= 16;
printState("0|0|z~", zTilde);
if (g_debugMode > 0) printState("0|0|z~", zTilde);
// int zerocounter = 0 ;
for (int i = 0; i < 8; i++) {
// the key on index i is first a bit from y
// then six bits from z,
@ -317,8 +318,6 @@ void hash0(uint64_t c, uint8_t k[8]) {
// First, place y(7-i) leftmost in k
k[i] |= (y << (7 - i)) & 0x80 ;
uint8_t zTilde_i = getSixBitByte(zTilde, i);
// zTildeI is now on the form 00XXXXXX
// with one leftshift, it'll be
@ -342,9 +341,6 @@ void hash0(uint64_t c, uint8_t k[8]) {
k[i] |= zTilde_i & 0x7E;
k[i] |= (~p_i) & 1;
}
// if ((k[i] & 1) == 0) {
// zerocounter++;
// }
}
}
/**
@ -354,18 +350,17 @@ void hash0(uint64_t c, uint8_t k[8]) {
* @param div_key
*/
void diversifyKey(uint8_t *csn, uint8_t *key, uint8_t *div_key) {
// Prepare the DES key
mbedtls_des_setkey_enc(&ctx_enc, key);
uint8_t crypted_csn[8] = {0};
// Calculate DES(CSN, KEY)
mbedtls_des_context ctx_enc;
mbedtls_des_setkey_enc(&ctx_enc, key);
mbedtls_des_crypt_ecb(&ctx_enc, csn, crypted_csn);
mbedtls_des_free(&ctx_enc);
//Calculate HASH0(DES))
uint64_t c_csn = x_bytes_to_num(crypted_csn, sizeof(crypted_csn));
//uint64_t crypted_csn_swapped = swapZvalues(crypt_csn);
hash0(c_csn, div_key);
}
/*
@ -420,28 +415,38 @@ typedef struct {
uint8_t uid[8];
uint8_t t_key[8];
uint8_t div_key[8];
} Testcase;
} testcase_t;
static int testDES(Testcase testcase) {
static int testDES(uint8_t *key, testcase_t testcase) {
uint8_t des_encrypted_csn[8] = {0};
uint8_t decrypted[8] = {0};
uint8_t div_key[8] = {0};
mbedtls_des_context ctx_enc;
mbedtls_des_context ctx_dec;
mbedtls_des_setkey_enc(&ctx_enc, key);
mbedtls_des_setkey_dec(&ctx_dec, key);
int retval = mbedtls_des_crypt_ecb(&ctx_enc, testcase.uid, des_encrypted_csn);
retval |= mbedtls_des_crypt_ecb(&ctx_dec, des_encrypted_csn, decrypted);
mbedtls_des_free(&ctx_enc);
mbedtls_des_free(&ctx_dec);
if (memcmp(testcase.uid, decrypted, 8) != 0) {
//Decryption fail
PrintAndLogEx(FAILED, "Encryption <-> Decryption FAIL");
printarr("Input", testcase.uid, 8);
printarr("Decrypted", decrypted, 8);
printarr(" input", testcase.uid, 8);
printarr(" decrypted", decrypted, 8);
retval = 1;
}
if (memcmp(des_encrypted_csn, testcase.t_key, 8) != 0) {
//Encryption fail
PrintAndLogEx(FAILED, "Encryption != Expected result");
printarr("Output", des_encrypted_csn, 8);
printarr("Expected", testcase.t_key, 8);
printarr(" output", des_encrypted_csn, 8);
printarr(" expected", testcase.t_key, 8);
retval = 1;
}
uint64_t crypted_csn = x_bytes_to_num(des_encrypted_csn, 8);
@ -453,7 +458,7 @@ static int testDES(Testcase testcase) {
printarr(" csn ", testcase.uid, 8);
printarr("{csn} ", des_encrypted_csn, 8);
printarr("hash0 ", div_key, 8);
printarr("Expected", testcase.div_key, 8);
printarr(" expected", testcase.div_key, 8);
retval = 1;
}
return retval;
@ -461,9 +466,12 @@ static int testDES(Testcase testcase) {
static bool des_getParityBitFromKey(uint8_t key) {
// The top 7 bits is used
bool parity = ((key & 0x80) >> 7)
^ ((key & 0x40) >> 6) ^ ((key & 0x20) >> 5)
^ ((key & 0x10) >> 4) ^ ((key & 0x08) >> 3)
^ ((key & 0x04) >> 2) ^ ((key & 0x02) >> 1);
^ ((key & 0x40) >> 6)
^ ((key & 0x20) >> 5)
^ ((key & 0x10) >> 4)
^ ((key & 0x08) >> 3)
^ ((key & 0x04) >> 2)
^ ((key & 0x02) >> 1);
return !parity;
}
@ -480,11 +488,11 @@ static void des_checkParity(uint8_t *key) {
if (fails) {
PrintAndLogEx(FAILED, "parity fails: %d", fails);
} else {
PrintAndLogEx(SUCCESS, "Key syntax is with parity bits inside each byte");
PrintAndLogEx(SUCCESS, " Key syntax is with parity bits inside each byte (%s)", _GREEN_("ok"));
}
}
Testcase testcases[] = {
testcase_t testcases[] = {
{{0x8B, 0xAC, 0x60, 0x1F, 0x53, 0xB8, 0xED, 0x11}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xAE, 0x51, 0xE5, 0x62, 0xE7, 0x9A, 0x99, 0x39}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, {0x04, 0x02, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
@ -555,14 +563,14 @@ Testcase testcases[] = {
{{0}, {0}, {0}}
};
static int testKeyDiversificationWithMasterkeyTestcases(void) {
static int testKeyDiversificationWithMasterkeyTestcases(uint8_t *key) {
int i, error = 0;
uint8_t empty[8] = {0};
PrintAndLogEx(INFO, "Testing encryption/decryption");
for (i = 0; memcmp(testcases + i, empty, 8); i++)
error += testDES(testcases[i]);
error += testDES(key, testcases[i]);
if (error)
PrintAndLogEx(FAILED, "%d errors occurred (%d testcases)", error, i);
@ -581,7 +589,7 @@ static int testCryptedCSN(uint64_t crypted_csn, uint64_t expected) {
PrintAndLogEx(DEBUG, "");
PrintAndLogEx(DEBUG, " {csn} %"PRIx64, crypted_csn);
PrintAndLogEx(DEBUG, " {csn-revz} %"PRIx64, crypted_csn_swapped);
PrintAndLogEx(DEBUG, " hash0 %"PRIx64 " (%s)", resultbyte, (resultbyte == expected) ? _GREEN_("OK") : _RED_("FAIL"));
PrintAndLogEx(DEBUG, " hash0 %"PRIx64 " (%s)", resultbyte, (resultbyte == expected) ? _GREEN_("ok") : _RED_("fail"));
if (resultbyte != expected) {
PrintAndLogEx(DEBUG, " expected " _YELLOW_("%"PRIx64), expected);
@ -590,19 +598,22 @@ static int testCryptedCSN(uint64_t crypted_csn, uint64_t expected) {
return PM3_SUCCESS;
}
static int testDES2(uint64_t csn, uint64_t expected) {
static int testDES2(uint8_t *key, uint64_t csn, uint64_t expected) {
uint8_t result[8] = {0};
uint8_t input[8] = {0};
PrintAndLogEx(DEBUG, " csn %"PRIx64, csn);
x_num_to_bytes(csn, 8, input);
mbedtls_des_context ctx_enc;
mbedtls_des_setkey_enc(&ctx_enc, key);
mbedtls_des_crypt_ecb(&ctx_enc, input, result);
mbedtls_des_free(&ctx_enc);
uint64_t crypt_csn = x_bytes_to_num(result, 8);
PrintAndLogEx(DEBUG, " {csn} %"PRIx64, crypt_csn);
PrintAndLogEx(DEBUG, " expected %"PRIx64 " (%s)", expected, (expected == crypt_csn) ? _GREEN_("OK") : _RED_("FAIL"));
PrintAndLogEx(DEBUG, " expected %"PRIx64 " (%s)", expected, (expected == crypt_csn) ? _GREEN_("ok") : _RED_("fail") );
if (expected != crypt_csn)
return PM3_ESOFT;
@ -619,8 +630,7 @@ static int doTestsWithKnownInputs(void) {
PrintAndLogEx(INFO, "Testing DES encryption");
uint8_t key[8] = {0x6c, 0x8d, 0x44, 0xf9, 0x2a, 0x2d, 0x01, 0xbf};
mbedtls_des_setkey_enc(&ctx_enc, key);
testDES2(0xbbbbaaaabbbbeeee, 0xd6ad3ca619659e6b);
testDES2(key, 0xbbbbaaaabbbbeeee, 0xd6ad3ca619659e6b);
PrintAndLogEx(INFO, "Testing hashing algorithm");
@ -681,11 +691,10 @@ int doKeyTests(void) {
PrintAndLogEx(SUCCESS, "Key present");
PrintAndLogEx(SUCCESS, "Checking key parity...");
des_checkParity(key);
mbedtls_des_setkey_enc(&ctx_enc, key);
mbedtls_des_setkey_dec(&ctx_dec, key);
// Test hashing functions
PrintAndLogEx(SUCCESS, "The following tests require the correct 8-byte master key");
testKeyDiversificationWithMasterkeyTestcases();
testKeyDiversificationWithMasterkeyTestcases(key);
}
}
PrintAndLogEx(INFO, "Testing key diversification with non-sensitive keys...");

View file

@ -1347,7 +1347,7 @@ int set_pm3_libraries(lua_State *L) {
{"WaitForResponseTimeout", l_WaitForResponseTimeout},
{"mfDarkside", l_mfDarkside},
{"foobar", l_foobar},
{"kbd_enter_pressed", l_kbd_enter_pressed},
{"kbd_enter_pressed", l_kbd_enter_pressed},
{"clearCommandBuffer", l_clearCommandBuffer},
{"console", l_CmdConsole},
{"iso15693_crc", l_iso15693_crc},

View file

@ -109,19 +109,20 @@ Print keystore
```
Options
---
p : print keys loaded into memory
-p, --print Print keys loaded into memory
pm3 --> hf iclass managekeys p
pm3 --> hf iclass managekeys -p
```
Add key to keystore [0-7]
```
Options
---
n <keynbr> : specify the keyNbr to set in memory
k <key> : set a key in memory
-f, --file <filename> Specify a filename to use with load or save operations
--ki <dec> Specify key index to set key in memory
pm3 --> hf iclass managekeys n 3 k AFA785A7DAB33378
pm3 --> hf iclass managekeys --ki 3 -k AFA785A7DAB33378
```
Encrypt iCLASS Block
@ -167,20 +168,23 @@ Simulate iCLASS
```
Options
---
0 <CSN> simulate the given CSN
-t, --type <int> Simulation type to use
--csn <hex> Specify CSN as 8 bytes (16 hex symbols) to use with sim type 0
Types:
0 simulate the given CSN
1 simulate default CSN
2 Runs online part of LOCLASS attack
3 Full simulation using emulator memory (see 'hf iclass eload')
4 Runs online part of LOCLASS attack against reader in keyroll mode
pm3 --> hf iclass sim 3
pm3 --> hf iclass sim -t 3
```
Simulate iCLASS Sequence
```
pm3 --> hf iclass dump --ki 0
pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin
pm3 --> hf iclass sim 3
pm3 --> hf iclass sim -t 3
```
Extract custom iCLASS key (loclass attack)
@ -189,11 +193,11 @@ Options
---
f <filename> : specify a filename to clone from
k <key> : Access Key as 16 hex symbols or 1 hex to select key from memory
e : If 'e' is specified, elite computations applied to key
--elite : Elite computations applied to key
pm3 --> hf iclass sim 2
pm3 --> hf iclass sim -t 2
pm3 --> hf iclass loclass -f iclass_mac_attack.bin
pm3 --> hf iclass managekeys n 7 k <Kcus>
pm3 --> hf iclass managekeys --ki 7 -k <Kcus>
pm3 --> hf iclass dump --ki 7 --elite
```
@ -201,13 +205,14 @@ Verify custom iCLASS key
```
Options
---
f <filename> : Dictionary file with default iCLASS keys
u : CSN
p : EPURSE
m : macs
e : elite
-f, --file <filename> Dictionary file with default iclass keys
--csn <hex> Specify CSN as 8 bytes (16 hex symbols)
--epurse <hex> Specify ePurse as 8 bytes (16 hex symbols)
--macs <hex> MACs
--raw no computations applied to key (raw)
--elite Elite computations applied to key
pm3 --> hf iclass lookup u 010a0ffff7ff12e0 p feffffffffffffff m 66348979153c41b9 f iclass_default_keys e
pm3 --> hf iclass lookup --csn 010a0ffff7ff12e0 --epurse feffffffffffffff --macs 66348979153c41b9 -f iclass_default_keys --elite
```
## MIFARE

329
doc/cliparser_todo.txt Normal file
View file

@ -0,0 +1,329 @@
clear
pref
rem
quit
exit
analyse lcr
analyse crc
analyse chksum
analyse dates
analyse tea
analyse lfsr
analyse a
analyse nuid
analyse demodbuff
analyse freq
data biphaserawdecode
data detectclock
data fsktonrz
data manrawdecode
data rawdemod
data askedgedetect
data autocorr
data dirthreshold
data hide
data hpf
data iir
data grid
data ltrim
data mtrim
data norm
data plot
data rtrim
data setgraphmarkers
data shiftgraphzero
data zerocrossings
data convertbitstream
data getbitstream
data bin2hex
data bitsamples
data clear
data hexsamples
data hex2bin
data print
data samples
data setdebugmode
data tune
emv list
hf list
hf tune
hf search
hf sniff
hf 14a list
hf 14a reader
hf 14a cuids
hf 14a sim
hf 14a sniff
hf 14a config
hf 14b list
hf 14b sriwrite
hf 15 list
hf 15 dump
hf 15 info
hf 15 raw
hf 15 rdbl
hf 15 readmulti
hf 15 restore
hf 15 wrbl
hf 15 writeafi
hf 15 writedsfid
hf epa cnonces
hf epa preplay
hf felica list
hf felica reader
hf felica sniff
hf felica raw
hf felica rdunencrypted
hf felica wrunencrypted
hf felica rqservice
hf felica rqresponse
hf felica scsvcode
hf felica rqsyscode
hf felica auth1
hf felica auth2
hf felica rqspecver
hf felica resetmode
hf felica litesim
hf felica litedump
hf fido list
hf fido info
hf iclass info
hf iclass list
hf legic list
hf legic reader
hf legic info
hf legic dump
hf legic restore
hf legic rdbl
hf legic sim
hf legic wrbl
hf legic crc
hf legic eload
hf legic esave
hf legic wipe
hf lto dump
hf lto restore
hf lto info
hf lto rdbl
hf lto wrbl
hf lto list
hf mf list
hf mf darkside
hf mf nested
hf mf hardnested
hf mf staticnested
hf mf autopwn
hf mf nack
hf mf chk
hf mf fchk
hf mf decrypt
hf mf dump
hf mf rdbl
hf mf rdsc
hf mf restore
hf mf setmod
hf mf wrbl
hf mf sim
hf mf ecfill
hf mf eclr
hf mf egetblk
hf mf egetsc
hf mf ekeyprn
hf mf eload
hf mf esave
hf mf eset
hf mf eview
hf mf cgetblk
hf mf cgetsc
hf mf cload
hf mf csave
hf mf csetblk
hf mf csetuid
hf mf cview
hf mf gen3uid
hf mf gen3blk
hf mf gen3freeze
hf mf ice
hf mfp info
hf mfu info
hf mfu dump
hf mfu restore
hf mfu eload
hf mfu rdbl
hf mfu wrbl
hf mfu cauth
hf mfu setpwd
hf mfu setuid
hf mfu sim
hf mfu gen
hf mfu pwdgen
hf mfu otptear
hf mfdes enum
hf mfdes getuid
hf mfdes info
hf mfdes list
hf st list
hf thinfilm info
hf thinfilm list
hf thinfilm sim
hf topaz list
hf topaz info
hf topaz reader
hf topaz sim
hf topaz sniff
hf topaz raw
hw connect
hw dbg
hw detectreader
hw fpgaoff
hw lcd
hw lcdreset
hw ping
hw readmem
hw reset
hw setlfdivisor
hw setmux
hw standalone
hw status
hw tia
hw tune
hw version
lf config
lf cmdread
lf read
lf search
lf sim
lf simask
lf simfsk
lf simpsk
lf simbidir
lf sniff
lf tune
lf awid demod
lf awid read
lf awid clone
lf awid sim
lf awid brute
lf awid watch
lf cotag demod
lf cotag read
lf destron demod
lf destron read
lf destron sim
lf em 410x_demod
lf em 410x_read
lf em 410x_sim
lf em 410x_brute
lf em 410x_watch
lf em 410x_spoof
lf em 410x_clone
lf em 4x05_demod
lf em 4x05_dump
lf em 4x05_wipe
lf em 4x05_info
lf em 4x05_read
lf em 4x05_write
lf em 4x50_dump
lf em 4x50_info
lf em 4x50_write
lf em 4x50_write_password
lf em 4x50_read
lf em 4x50_wipe
lf fdxb demod
lf fdxb read
lf fdxb clone
lf fdxb sim
lf gallagher demod
lf gallagher read
lf gallagher clone
lf gallagher sim
lf gproxii demod
lf gproxii read
lf gproxii clone
lf gproxii sim
lf hid demod
lf hid read
lf hitag list
lf hitag info
lf hitag reader
lf hitag sim
lf hitag sniff
lf hitag writer
lf hitag dump
lf hitag cc
lf idteck demod
lf idteck read
lf indala demod
lf indala altdemod
lf indala read
lf indala sim
lf io demod
lf io read
lf io clone
lf io sim
lf io watch
lf jablotron demod
lf jablotron read
lf jablotron clone
lf jablotron sim
lf keri demod
lf motorola demod
lf motorola sim
lf nedap demod
lf nedap generate
lf nedap read
lf nedap clone
lf nedap sim
lf nexwatch demod
lf noralsy demod
lf pac demod
lf paradox demod
lf pcf7931 read
lf pcf7931 write
lf pcf7931 config
lf presco demod
lf pyramid demod
lf securakey demod
lf ti demod
lf ti write
lf t55xx config
lf t55xx dangerraw
lf t55xx detect
lf t55xx deviceconfig
lf t55xx dump
lf t55xx info
lf t55xx p1detect
lf t55xx read
lf t55xx resetread
lf t55xx restore
lf t55xx trace
lf t55xx wakeup
lf t55xx write
lf t55xx bruteforce
lf t55xx chk
lf t55xx protect
lf t55xx recoverpw
lf t55xx sniff
lf t55xx special
lf t55xx wipe
lf viking demod
lf visa2000 demod
mem spiffs
smart list
smart info
smart reader
smart raw
smart upgrade
smart setclock
smart brute
script list
script run
usart btpin
usart btfactory
usart tx
usart rx
usart txrx
usart txhex
usart rxhex
usart config
wiegand list

View file

@ -38,7 +38,6 @@ Check column "offline" for their availability.
|`analyse nuid `|Y |`create NUID from 7byte UID`
|`analyse demodbuff `|Y |`Load binary string to demodbuffer`
|`analyse freq `|Y |`Calc wave lengths`
|`analyse foo `|Y |`muxer`
### data
@ -733,7 +732,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`lf keri help `|Y |`This help`
|`lf keri demod `|Y |`Demodulate an KERI tag from the GraphBuffer`
|`lf keri read `|N |`Attempt to read and extract tag data from the antenna`
|`lf keri reader `|N |`Attempt to read and extract tag data from the antenna`
|`lf keri clone `|N |`clone KERI tag to T55x7 or Q5/T5555`
|`lf keri sim `|N |`simulate KERI tag`
@ -746,7 +745,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`lf motorola help `|Y |`This help`
|`lf motorola demod `|Y |`Demodulate an MOTOROLA tag from the GraphBuffer`
|`lf motorola read `|N |`Attempt to read and extract tag data from the antenna`
|`lf motorola reader `|N |`Attempt to read and extract tag data from the antenna`
|`lf motorola clone `|N |`clone MOTOROLA tag to T55x7`
|`lf motorola sim `|N |`simulate MOTOROLA tag`

View file

@ -4,7 +4,7 @@ This document is primarily intended for understanding `hf iclass loclass` and fi
LOCLASS aim is to recover the used masterkey for that specific reader configured in Elite mode / High Security mode.
LOCLASS, is a two part attack. First is the online part where you gather needed information from the reader by presenting a carefully selected CSN and save the responses to file. For the first part you run `hf iclass sim 2` and take notice of the saved filename.
LOCLASS, is a two part attack. First is the online part where you gather needed information from the reader by presenting a carefully selected CSN and save the responses to file. For the first part you run `hf iclass sim -t 2` and take notice of the saved filename.
The second part is offline, where the information gathered from the first step is used in a series of DES operations to figure out the used
masterkey.
@ -21,6 +21,6 @@ run `hf iclass loclass --test`.
This test mode uses two files.
- `iclass_dump.bin`
this is a sample file from `hf iclass sim 2`, with complete keytable recovery, using 128 carefully selected CSN and the file contains the MAC results from reader.
this is a sample file from `hf iclass sim -t 2`, with complete keytable recovery, using 128 carefully selected CSN and the file contains the MAC results from reader.
- `iclass_key.bin`
this is file shall contain the legacy masterkey, AA1 key. loclass uses it to verify that permutation / reversing / generation of key is correct.

View file

@ -433,7 +433,7 @@ while true; do
"Paradox - ID: 004209dea FC: 96 Card: 40426, Checksum: b2, Raw: 0f55555695596a6a9999a59a"; then break; fi
if ! CheckExecute slow "lf T55 presco test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_presco.pm3; lf search 1'" "Presco ID found"; then break; fi
if ! CheckExecute slow "lf T55 presco test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_presco.pm3; lf presco demod'" \
"Presco - Card: 1E8021D9, Raw: 10D0000000000000000000001E8021D9"; then break; fi
"Presco Site code: 30 User code: 8665 Full code: 1E8021D9 Raw: 10D0000000000000000000001E8021D9"; then break; fi
if ! CheckExecute slow "lf T55 pyramid test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_pyramid.pm3; lf search 1'" "Pyramid ID found"; then break; fi
if ! CheckExecute slow "lf T55 pyramid test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_pyramid.pm3; lf pyramid demod'" \
"Pyramid - len: 26, FC: 123 Card: 11223 - Wiegand: 2f657ae, Raw: 00010101010101010101016eb35e5da4"; then break; fi
@ -450,7 +450,7 @@ while true; do
echo -e "\n${C_BLUE}Testing HF:${C_NC}"
if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi
if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:"; then break; fi
if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified ok"; then break; fi
if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified (ok)"; then break; fi
if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ ok"; then break; fi
if ! $SLOWTESTS; then
if ! CheckExecute "hf iclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi