mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
chg: 'hf mf nack' - extracted in into mifarehost for easier usage in other cmds like
'hf 14a info' chg: 'hf mf nack' - changes on devices side from @doegox Thanks!
This commit is contained in:
parent
5f87b24493
commit
0a1a48df01
5 changed files with 88 additions and 50 deletions
|
@ -2552,6 +2552,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
|||
|
||||
/*
|
||||
* Mifare Classic NACK-bug detection
|
||||
* Thanks to @doegox for the feedback and new approaches.
|
||||
*/
|
||||
void DetectNACKbug() {
|
||||
|
||||
|
@ -2571,6 +2572,7 @@ void DetectNACKbug() {
|
|||
uint16_t sync_tries = 0;
|
||||
uint32_t sync_time = 0;
|
||||
bool have_uid = false;
|
||||
bool received_nack;
|
||||
|
||||
// Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
|
||||
uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH;
|
||||
|
@ -2592,6 +2594,18 @@ void DetectNACKbug() {
|
|||
uint16_t i;
|
||||
for (i = 0; true; ++i) {
|
||||
|
||||
received_nack = false;
|
||||
if ((i==10) && (num_nacks == i)) {
|
||||
// Cards always leaks a NACK, no matter the parity
|
||||
isOK = 2;
|
||||
break;
|
||||
}
|
||||
if ( (i > 1) && (num_nacks == 1) ) {
|
||||
// NACK bug
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// Test if the action was cancelled
|
||||
|
@ -2639,7 +2653,7 @@ void DetectNACKbug() {
|
|||
// Receive the (4 Byte) "random" nonce from TAG
|
||||
if (!ReaderReceive(receivedAnswer, receivedAnswerPar))
|
||||
continue;
|
||||
|
||||
|
||||
previous_nt = nt;
|
||||
nt = bytes_to_num(receivedAnswer, 4);
|
||||
|
||||
|
@ -2735,7 +2749,7 @@ void DetectNACKbug() {
|
|||
// Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
|
||||
if (ReaderReceive(receivedAnswer, receivedAnswerPar)) {
|
||||
catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer
|
||||
isOK = 1;
|
||||
received_nack = true;
|
||||
num_nacks++;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
|
|||
|
||||
#GCC_GTEQ_490 := $(shell expr `gcc --version | awk '/gcc/{print $$NF;}' | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40900)
|
||||
GCC_VERSION := $(shell gcc --version | awk '/gcc/{print $$NF;}' | sed -e 's/\-.*//g' -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
|
||||
CLANG_VERSION := $(shell gcc --version | awk '/Apple LLVM version/{print $$4;}' | sed -e -e 's/\-.*//g' 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
|
||||
CLANG_VERSION := $(shell gcc --version | awk '/Apple LLVM version/{print $$4;}' | sed -e 's/\-.*//g' -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
|
||||
ifneq ($(CLANG_VERSION), )
|
||||
SUPPORTS_AVX512 := $(shell [ $(CLANG_VERSION) -ge 80000 ] && echo "True" )
|
||||
endif
|
||||
|
|
|
@ -321,6 +321,17 @@ int usage_hf14_csave(void){
|
|||
PrintAndLog(" hf mf csave 4 o filename");
|
||||
return 0;
|
||||
}
|
||||
int usage_hf14_nack(void) {
|
||||
PrintAndLog("Test a mifare classic based card for the NACK bug.");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Usage: hf mf nack [h] [v]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h this help");
|
||||
PrintAndLog(" v verbose");
|
||||
PrintAndLog("samples:");
|
||||
PrintAndLog(" hf mf nack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMifare(const char *Cmd) {
|
||||
uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA;
|
||||
|
@ -2851,43 +2862,15 @@ int CmdHf14AMfSetMod(const char *Cmd) {
|
|||
// Mifare NACK bug detection
|
||||
int CmdHf14AMfNack(const char *Cmd) {
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
bool verbose = false;
|
||||
char ctmp = param_getchar(Cmd, 0);
|
||||
if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_nack();
|
||||
if ( ctmp == 'v' || ctmp == 'V' ) verbose = true;
|
||||
|
||||
if ( verbose )
|
||||
PrintAndLog("Started testing card for NACK bug. Press key to abort");
|
||||
|
||||
PrintAndLog("Started testing card for NACK bug");
|
||||
|
||||
while (true) {
|
||||
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
if (ukbhit()) {
|
||||
int gc = getchar(); (void)gc;
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
int32_t ok = resp.arg[0];
|
||||
uint32_t nacks = resp.arg[1];
|
||||
uint32_t auths = resp.arg[2];
|
||||
|
||||
PrintAndLog("\nNum of sent auth requestes : %u", auths);
|
||||
PrintAndLog("Num of received NACK : %u", nacks);
|
||||
switch( ok ) {
|
||||
case -1 : PrintAndLog("Button pressed. Aborted."); return 1;
|
||||
case -2 : PrintAndLog("Card answers NACK, (most likely a clone)"); return 1;
|
||||
case -3 : PrintAndLog("Card random number generator is not predictable)."); return 1;
|
||||
case -4 : PrintAndLog("Card random number generator seems to be based on the wellknown");
|
||||
PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour."); return 1;
|
||||
case 1 : PrintAndLog("Card has NACK bug."); return 1;
|
||||
case 0 : PrintAndLog("Card has not NACK bug."); return 1;
|
||||
default : PrintAndLog(" errorcode from device [%i]", ok); return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
detect_classic_nackbug(verbose);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i
|
|||
return i;
|
||||
}
|
||||
|
||||
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key)
|
||||
{
|
||||
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||
uint32_t uid = 0;
|
||||
uint32_t nt = 0, nr = 0;
|
||||
uint64_t par_list = 0, ks_list = 0;
|
||||
|
@ -852,15 +851,59 @@ bool detect_classic_prng(void){
|
|||
uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]);
|
||||
return validate_prng_nonce(nonce);
|
||||
}
|
||||
/* Detect Mifare Classic NACK bug */
|
||||
bool detect_classic_nackbug(void){
|
||||
/* Detect Mifare Classic NACK bug
|
||||
|
||||
returns:
|
||||
0 = error during test / aborted
|
||||
1 = has nack bug
|
||||
2 = has not nack bug
|
||||
3 = always leak nacks (clones)
|
||||
*/
|
||||
int detect_classic_nackbug(bool verbose){
|
||||
|
||||
// get nonce?
|
||||
UsbCommand c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
// loop max 256 times,
|
||||
// fixed nonce, different parity every call
|
||||
if ( verbose )
|
||||
printf("Press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n");
|
||||
|
||||
while (true) {
|
||||
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
if (ukbhit()) {
|
||||
int gc = getchar(); (void)gc;
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
int32_t ok = resp.arg[0];
|
||||
uint32_t nacks = resp.arg[1];
|
||||
uint32_t auths = resp.arg[2];
|
||||
if ( verbose ) {
|
||||
PrintAndLog("\nNum of sent auth requests : %u", auths);
|
||||
PrintAndLog("Num of received NACK : %u", nacks);
|
||||
}
|
||||
switch( ok ) {
|
||||
case -1 : if (verbose) PrintAndLog("Button pressed. Aborted."); return 0;
|
||||
case -3 : if (verbose) PrintAndLog("Card random number generator is not predictable)."); return 0;
|
||||
case -4 : if (verbose) {
|
||||
PrintAndLog("Card random number generator seems to be based on the well-known generating polynomial");
|
||||
PrintAndLog("with 16 effective bits only, but shows unexpected behavior, try again.");
|
||||
return 0;
|
||||
}
|
||||
case 2 : PrintAndLog("Card always leak NACK."); return 3;
|
||||
case 1 : PrintAndLog("Card has NACK bug."); return 1;
|
||||
case 0 : PrintAndLog("Card has not NACK bug."); return 2;
|
||||
default : PrintAndLog(" errorcode from device [%i]", ok); return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* try to see if card responses to "chinese magic backdoor" commands. */
|
||||
void detect_classic_magic(void) {
|
||||
|
|
|
@ -67,8 +67,6 @@ typedef struct {
|
|||
//uint8_t foundKey[2];
|
||||
} icesector_t;
|
||||
|
||||
|
||||
|
||||
extern char logHexFileName[FILE_PATH_SIZE];
|
||||
|
||||
extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key);
|
||||
|
@ -95,6 +93,6 @@ extern int saveTraceCard(void);
|
|||
extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||
|
||||
extern bool detect_classic_prng(void);
|
||||
extern bool detect_classic_nackbug(void);
|
||||
extern int detect_classic_nackbug(bool verbose);
|
||||
extern void detect_classic_magic(void);
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue