mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge branch 'master' into allin
update 201129
This commit is contained in:
commit
72b21f018e
20 changed files with 1235 additions and 577 deletions
|
@ -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)
|
||||
|
|
9
Makefile
9
Makefile
|
@ -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 )
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -105,6 +105,11 @@ c934fe34d934
|
|||
cccccccccccc
|
||||
dddddddddddd
|
||||
eeeeeeeeeeee
|
||||
#
|
||||
# elevator
|
||||
# data from forum
|
||||
FFFFFF545846
|
||||
#
|
||||
f1a97341a9fc
|
||||
44ab09010845 # hotel system
|
||||
85fed980ea5a # hotel system
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 [i−1] )
|
||||
rk(key64, i, temp_output);
|
||||
//y [i] = DES enc (rk(K cus , i), y [i−1] )
|
||||
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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
329
doc/cliparser_todo.txt
Normal 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
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue