Add mf_nonce_brute from https://github.com/iceman1001/mf_nonce_brute and merge to pm3 Makefile

This commit is contained in:
Philippe Teuwen 2020-05-15 13:07:27 +02:00
parent f7bbf8b59f
commit a739d33398
11 changed files with 698 additions and 6 deletions

2
.gitignore vendored
View file

@ -87,7 +87,7 @@ client/dumps/*
*.ice
*.new
armsrc/TEMP EMV/*
tools/mf_nonce_brute/*
tools/mf_nonce_brute/mf_nonce_brute
tools/andrew/*
tools/jtag_openocd/openocd_configuration
ppls patches/*

View file

@ -17,6 +17,8 @@ endif
CFLAGS ?= $(DEFCFLAGS)
CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
LDFLAGS += $(MYLDFLAGS)
LDLIBS += $(MYLDLIBS)
vpath %.c $(MYSRCPATHS)
@ -66,7 +68,7 @@ $(BINDIR)/$(LIB_A): $(MYOBJS)
$(BINDIR)/% : $(OBJDIR)/%.o $(MYOBJS) $(MYLIBS)
$(info [=] LD $(notdir $@))
$(Q)$(LD) $(LDFLAGS) $(MYOBJS) $< -o $@ $(MYLIBS)
$(Q)$(LD) $(LDFLAGS) $(MYOBJS) $< -o $@ $(MYLIBS) $(MYLDLIBS)
$(OBJDIR)/%.o : %.c | $(OBJDIR)
$(info [-] CC $<)

View file

@ -11,10 +11,6 @@ get_crapto1:
$(WGET) http://crapto1.netgarage.org/crapto1-v3.3.tar.xz
$(TAR) Jxvf crapto1-v3.3.tar.xz -C crapto1-v3.3
get_nonce_bf:
# $(GIT) https://github.com/J-Run/mf_key_brute.git mf_key_brute
$(GIT) https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute
get_xorsearch:
$(MKDIR) xorsearch
$(WGET) https://didierstevens.com/files/software/XORSearch_V1_11_2.zip

View file

@ -0,0 +1,20 @@
MYSRCPATHS = ../../common ../../common/crapto1
MYSRCS = crypto1.c crapto1.c bucketsort.c iso14443crc.c sleep.c
MYINCLUDES = -I../../include -I../../common
MYCFLAGS =
MYDEFS =
MYLDLIBS = -lpthread
BINS = mf_nonce_brute
INSTALLTOOLS = $(BINS)
include ../../Makefile.host
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
mf_nonce_brute : $(OBJDIR)/mf_nonce_brute.o $(MYOBJS)

View file

@ -0,0 +1,132 @@
mf_nonce_brute
==============
Nested authentificated sector key recovery tool
-----------------------------------------------
Compatible tags:
* Mifare Classic 1k (4k)
* Mifare Plus in SL1 mode
To recover keys to nested authentificated sectors you need a reader-card communication log. To get it use
hardware tools that able to sniff communication (for example Proxmark3 or HydraNFC).
This enhanced version:
First 2 bytes should be bruteforced in phase 2 with mf_key_brute tool that interacts with a card.
Sample trace:
```
93 70 fd ac f6 d8 7f 21 4f // select card with UID fdacf6d8
TAG 08 b6 dd // sak
60 04 d1 3d // wanna auth block 0x04 with A key
TAG ed 12 9c 74 // 1st auth clear text nt
55 53 9f cc 41 8d e8 f3 // nr', ar' (nr^ks1, ar^ks2 )
TAG 05 49 e1 65 // at' ( at^ks3 )
03 24 26 56 // wanna read block 0x04
TAG ac 69 ef 58 45 e1 c2 1d a9 47 a5 94 54 ef 5d c7 1e a9 // block 0x04 content
d4 3e a8 aa
TAG 8e 8e e3 e6 e9 e2 5f dd f6 08 ce fb 02 6a db 75 94 2f
79 77 68 3c
TAG e0 00 00 80 80 08 cc 80 08 9c 82 e0 68 64 60 30 91 60 // 18 bytes = 16 byte content + 2 bytes crc
ea 88 c3 c2 // 4 byte read cmd
TAG a3 76 dc df c1 42 e0 ee c6 75 a4 ca eb 0c da eb 46 a0 // 18 bytes = 16 byte content + 2 bytes crc ks8 + crc
2d 27 ab 6f // wanna auth to 0x04 block with key B
-------Until this line we can recover key or decrypt communication with no troubles (see mfkey64 tool)--------------------------------
TAG 52 6e af 8b // nested auth encrypted tag nonce that we dont know
8e 21 3a 29 a4 80 7e 02 // nr_enc = nr^ks1, ar_enc = ar^ks2
TAG b9 43 74 8d // at_enc = at^ks3
e2 25 f8 32 // probably next command (actually is read block cmd, but we dont know it yet)
TAG 1f 26 82 8d 12 21 dd 42 c2 84 3e d0 26 7f 6b 2a 81 a9 // probably data
ba 85 1d 36 // probably read cmd
TAG 62 a8 78 69 ee 36 22 16 1c ff 4b 4e 69 cb 27 c2 e8 7e // probably data
a7 b1 c8 da // probably read cmd
TAG b2 fc 6c 65 60 ec 35 83 87 56 e3 7e 3c bf 38 b8 73 21 // probably data
99 92 13 55 // probably read cmd
TAG 93 5b 65 a3 1d 8c 75 b8 3a 63 e2 31 f0 d0 a9 24 9a f6 // probably data
```
Phase 1
-------
Syntax:
`mf_nonce_brute <uid> <{nt}> <nt_par_err> <{nr}> <{ar}> <ar_par_err> <{at}> <at_par_err> [<{next_command}>]`
Example: if `nt` in trace is `8c! 42 e6! 4e!`, then `nt` is `8c42e64e` and `nt_par_err` is `1011`
Example with parity (from this trace http://www.proxmark.org/forum/viewtopic.php?pid=550#p550) :
```
+ 561882: 1 : 26
+ 64: 2 : TAG 04 00
+ 10217: 2 : 93 20
+ 64: 5 : TAG 9c 59 9b 32 6c UID
+ 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30
+ 64: 3 : TAG 08 b6 dd
+ 923318: 4 : 60 00 f5 7b AUTH Block 0
+ 112: 4 : TAG 82 a4 16 6c Nonce Tag (NT)
+ 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! NR , AR
+ 64: 4 : TAG 5c! ad f4 39! AT
+ 811513: 4 : 8e 0e! 5d! b9 AUTH Block 0 (nested)
+ 112: 4 : TAG 5a! 92 0d! 85! Nonce Tag (NT)
+ 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 NR , AR
+ 64: 4 : TAG ca 7e! 0b! 63! AT
+ 670868: 4 : 3e! 70 9c! 8a
+ 112: 4 : TAG 36! 41 24! 79
+ 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27
+ 64: 4 : TAG 40! 6a! 99! 4b
+ 905612: 4 : c9 7c 64! 13! !crc
+ 112: 4 : TAG b5! ab! 1d! 2b
+ 6936: 8 : 7e! d2 5c! ca! 4b! 50! 88! c4 !crc
+ 64: 4 : TAG bf dd 01 be!
+ 987853: 4 : 56 98 49 d6! !crc
```
=>
```
./mf_nonce_brute 9c599b32 82a4166c 0000 a1e458ce 6eea41e0 0101 5cadf439 1001 3e709c8a
| | | | | | | | |
+UID +nt_enc | +nr_enc +ar_enc | +at_enc | +encrypted next cmd
+nt_par_err +at_par_err +at_par_err
```
These two taken from above use the plaintext tagnonce `nt`=`82a4166c`, they still find a possible key candidate.
```
./mf_nonce_brute 9c599b32 82a4166c 0000 a1e458ce 6eea41e0 0101 5cadf439 1001
./mf_nonce_brute 9c599b32 82a4166c 0000 98d76b77 d6c6e870 0000 ca7e0b63 0111
```
This one uses the encrypted tagnonce `nt`=`5a920d85`, it finds a valid key.
```
./mf_nonce_brute 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111
```
This one uses the encrypted tagnonce `nt`=`5a920d85` and the encrypted cmd `3e709c8a` to validate , it finds a valid key.
```
./mf_nonce_brute 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a
```
Full output:
```
$ ./mf_nonce_brute 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a
Mifare classic nested auth key recovery. Phase 1.
-------------------------------------------------
uid: 9c599b32
nt encrypted: 5a920d85
nt parity err: 1011
nr encrypted: 98d76b77
ar encrypted: d6c6e870
ar parity err: 0000
at encrypted: ca7e0b63
at parity err: 0111
next cmd enc: 3e709c8a
Starting 4 threads to bruteforce encrypted tag nonce last bytes
CMD enc(3e709c8a)
dec(6000f57b) <-- Valid cmd
Valid Key found: [ffffffffffff]
Time in mf_nonce_brute (Phase 1): 1763 ticks 2.0 seconds
```

View file

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO14443 CRC calculation code.
//-----------------------------------------------------------------------------
#include "iso14443crc.h"
static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc) {
ch = (ch ^ (unsigned char)((*lpwCrc) & 0x00FF));
ch = (ch ^ (ch << 4));
*lpwCrc = (*lpwCrc >> 8) ^ ((unsigned short) ch << 8) ^
((unsigned short) ch << 3) ^ ((unsigned short) ch >> 4);
return (*lpwCrc);
}
void ComputeCrc14443(int CrcType,
const unsigned char *Data, int Length,
unsigned char *TransmitFirst,
unsigned char *TransmitSecond) {
unsigned char chBlock;
unsigned short wCrc = CrcType;
do {
chBlock = *Data++;
UpdateCrc14443(chBlock, &wCrc);
} while (--Length);
if (CrcType == CRC_14443_B)
wCrc = ~wCrc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
*TransmitFirst = (unsigned char)(wCrc & 0xFF);
*TransmitSecond = (unsigned char)((wCrc >> 8) & 0xFF);
return;
}
int CheckCrc14443(int CrcType, const unsigned char *Data, int Length) {
unsigned char b1;
unsigned char b2;
if (Length < 3) return 0;
ComputeCrc14443(CrcType, Data, Length - 2, &b1, &b2);
if ((b1 == Data[Length - 2]) && (b2 == Data[Length - 1])) return 1;
return 0;
}

View file

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO14443 CRC calculation code.
//-----------------------------------------------------------------------------
#ifndef __ISO14443CRC_H
#define __ISO14443CRC_H
//-----------------------------------------------------------------------------
// Routines to compute the CRCs (two different flavours, just for confusion)
// required for ISO 14443, swiped directly from the spec.
//-----------------------------------------------------------------------------
#define CRC_14443_A 0x6363 /* ITU-V.41 */
#define CRC_14443_B 0xFFFF /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
#define CRC_ICLASS 0xE012 /* ICLASS PREFIX */
void ComputeCrc14443(int CrcType,
const unsigned char *Data, int Length,
unsigned char *TransmitFirst,
unsigned char *TransmitSecond);
int CheckCrc14443(int CrcType, const unsigned char *Data, int Length);
#endif

View file

@ -0,0 +1,395 @@
#define __STDC_FORMAT_MACROS
#define _USE_32BIT_TIME_T 1
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "crapto1/crapto1.h"
#include "protocol.h"
#include "iso14443crc.h"
#define odd_parity(i) (( (i) ^ (i)>>1 ^ (i)>>2 ^ (i)>>3 ^ (i)>>4 ^ (i)>>5 ^ (i)>>6 ^ (i)>>7 ^ 1) & 0x01)
// a global mutex to prevent interlaced printing from different threads
pthread_mutex_t print_lock;
//--------------------- define options here
uint32_t uid = 0; // serial number
uint32_t nt_enc = 0; // Encrypted tag nonce
uint32_t nr_enc = 0; // encrypted reader challenge
uint32_t ar_enc = 0; // encrypted reader response
uint32_t at_enc = 0; // encrypted tag response
uint32_t cmd_enc = 0; // next encrypted command to sector
uint32_t nt_par_err = 0;
uint32_t ar_par_err = 0;
uint32_t at_par_err = 0;
typedef struct thread_args {
uint16_t xored;
int thread;
int idx;
bool ev1;
} targs;
//------------------------------------------------------------------
uint8_t cmds[] = {
ISO14443A_CMD_READBLOCK,
ISO14443A_CMD_WRITEBLOCK,
MIFARE_AUTH_KEYA,
MIFARE_AUTH_KEYB,
MIFARE_CMD_INC,
MIFARE_CMD_DEC,
MIFARE_CMD_RESTORE,
MIFARE_CMD_TRANSFER
};
int global_counter = 0;
int global_fin_flag = 0;
int global_found = 0;
int global_found_candidate = 0;
size_t thread_count = 4;
static uint16_t parity_from_err(uint32_t data, uint16_t par_err) {
uint16_t par = 0;
par |= odd_parity((data >> 24) & 0xFF) ^ ((par_err >> 12) & 1);
par <<= 4;
par |= odd_parity((data >> 16) & 0xFF) ^ ((par_err >> 8) & 1);
par <<= 4;
par |= odd_parity((data >> 8) & 0xFF) ^ ((par_err >> 4) & 1);
par <<= 4;
par |= odd_parity(data & 0xFF) ^ (par_err & 1);
return par;
}
static uint16_t xored_bits(uint16_t nt_par, uint32_t ntenc, uint16_t ar_par, uint32_t arenc, uint16_t at_par, uint32_t atenc) {
uint16_t xored = 0;
uint8_t par;
//1st (1st nt)
par = (nt_par >> 12) & 1;
xored |= par ^ ((ntenc >> 16) & 1);
xored <<= 1;
//2nd (2nd nt)
par = (nt_par >> 8) & 1;
xored |= par ^ ((ntenc >> 8) & 1);
xored <<= 1;
//3rd (3rd nt)
par = (nt_par >> 4) & 1;
xored |= par ^ (ntenc & 1);
xored <<= 1;
//4th (1st ar)
par = (ar_par >> 12) & 1;
xored |= par ^ ((arenc >> 16) & 1);
xored <<= 1;
//5th (2nd ar)
par = (ar_par >> 8) & 1;
xored |= par ^ ((arenc >> 8) & 1);
xored <<= 1;
//6th (3rd ar)
par = (ar_par >> 4) & 1;
xored |= par ^ (arenc & 1);
xored <<= 1;
//7th (4th ar)
par = ar_par & 1;
xored |= par ^ ((atenc >> 24) & 1);
xored <<= 1;
//8th (1st at)
par = (at_par >> 12) & 1;
xored |= par ^ ((atenc >> 16) & 1);
xored <<= 1;
//9th (2nd at)
par = (at_par >> 8) & 1;
xored |= par ^ ((atenc >> 8) & 1);
xored <<= 1;
//10th (3rd at)
par = (at_par >> 4) & 1;
xored |= par ^ (atenc & 1);
return xored;
}
static bool candidate_nonce(uint32_t xored, uint32_t nt, bool ev1) {
uint8_t byte, check;
if (!ev1) {
//1st (1st nt)
byte = (nt >> 24) & 0xFF;
check = odd_parity(byte) ^ ((nt >> 16) & 1) ^ ((xored >> 9) & 1);
if (check) return false;
//2nd (2nd nt)
byte = (nt >> 16) & 0xFF;
check = odd_parity(byte) ^ ((nt >> 8) & 1) ^ ((xored >> 8) & 1);
if (check) return false;
}
//3rd (3rd nt)
byte = (nt >> 8) & 0xFF;
check = odd_parity(byte) ^ (nt & 1) ^ ((xored >> 7) & 1);
if (check) return false;
uint32_t ar = prng_successor(nt, 64);
//4th (1st ar)
byte = (ar >> 24) & 0xFF;
check = odd_parity(byte) ^ ((ar >> 16) & 1) ^ ((xored >> 6) & 1);
if (check) return false;
//5th (2nd ar)
byte = (ar >> 16) & 0x0FF;
check = odd_parity(byte) ^ ((ar >> 8) & 1) ^ ((xored >> 5) & 1);
if (check) return false;
//6th (3rd ar)
byte = (ar >> 8) & 0xFF;
check = odd_parity(byte) ^ (ar & 1) ^ ((xored >> 4) & 1);
if (check) return false;
uint32_t at = prng_successor(nt, 96);
//7th (4th ar)
byte = ar & 0xFF;
check = odd_parity(byte) ^ ((at >> 24) & 1) ^ ((xored >> 3) & 1);
if (check) return false;
//8th (1st at)
byte = (at >> 24) & 0xFF;
check = odd_parity(byte) ^ ((at >> 16) & 1) ^ ((xored >> 2) & 1);
if (check) return false;
//9th (2nd at)
byte = (at >> 16) & 0xFF;
check = odd_parity(byte) ^ ((at >> 8) & 1) ^ ((xored >> 1) & 1) ;
if (check) return false;
//10th (3rd at)
byte = (at >> 8) & 0xFF;
check = odd_parity(byte) ^ (at & 1) ^ (xored & 1);
if (check) return false;
return true;
}
static bool checkValidCmd(uint32_t decrypted) {
uint8_t cmd = (decrypted >> 24) & 0xFF;
for (int i = 0; i < sizeof(cmds); ++i) {
if (cmd == cmds[i])
return true;
}
return false;
}
static bool checkCRC(uint32_t decrypted) {
uint8_t data[] = {
(decrypted >> 24) & 0xFF,
(decrypted >> 16) & 0xFF,
(decrypted >> 8) & 0xFF,
decrypted & 0xFF
};
return CheckCrc14443(CRC_14443_A, data, sizeof(data));
}
static void *brute_thread(void *arguments) {
//int shift = (int)arg;
struct thread_args *args = (struct thread_args *) arguments;
struct Crypto1State *revstate;
uint64_t key; // recovered key candidate
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks3; // keystream used to encrypt tag response
uint32_t ks4; // keystream used to encrypt next command
uint32_t nt; // current tag nonce
uint32_t p64 = 0;
uint32_t count;
int found = 0;
// TC == 4 (
// threads calls 0 ev1 == false
// threads calls 0,1,2 ev1 == true
for (count = args->idx; count < 0xFFFF; count += thread_count - 1) {
found = global_found;
if (found) break;
nt = count << 16 | prng_successor(count, 16);
if (!candidate_nonce(args->xored, nt, args->ev1))
continue;
p64 = prng_successor(nt, 64);
ks2 = ar_enc ^ p64;
ks3 = at_enc ^ prng_successor(p64, 32);
revstate = lfsr_recovery64(ks2, ks3);
ks4 = crypto1_word(revstate, 0, 0);
if (ks4 != 0) {
// lock this section to avoid interlacing prints from different threats
pthread_mutex_lock(&print_lock);
if (args->ev1)
printf("\n**** Possible key candidate ****\n");
#if 0
printf("thread #%d idx %d %s\n", args->thread, args->idx, (args->ev1) ? "(Ev1)" : "");
printf("current nt(%08x) ar_enc(%08x) at_enc(%08x)\n", nt, ar_enc, at_enc);
printf("ks2:%08x\n", ks2);
printf("ks3:%08x\n", ks3);
printf("ks4:%08x\n", ks4);
#endif
if (cmd_enc) {
uint32_t decrypted = ks4 ^ cmd_enc;
printf("CMD enc(%08x)\n", cmd_enc);
printf(" dec(%08x)\t", decrypted);
uint8_t isOK = 0;
// check if cmd exists
isOK = checkValidCmd(decrypted);
// Add a crc-check.
isOK = checkCRC(decrypted);
if (!isOK) {
printf("<-- not a valid cmd\n");
pthread_mutex_unlock(&print_lock);
continue;
} else {
printf("<-- Valid cmd\n");
}
}
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, nr_enc, 1);
lfsr_rollback_word(revstate, uid ^ nt, 0);
crypto1_get_lfsr(revstate, &key);
free(revstate);
if (args->ev1) {
printf("\nKey candidate: [%012" PRIx64 "]\n\n", key);
__sync_fetch_and_add(&global_found_candidate, 1);
} else {
printf("\nValid Key found: [%012" PRIx64 "]\n\n", key);
__sync_fetch_and_add(&global_found, 1);
}
//release lock
pthread_mutex_unlock(&print_lock);
}
}
return NULL;
}
static int usage(void) {
printf(" syntax: mf_nonce_brute <uid> <nt> <nt_par_err> <nr> <ar> <ar_par_err> <at> <at_par_err> [<next_command>]\n\n");
printf(" example: nt in trace = 8c! 42 e6! 4e!\n");
printf(" nt = 8c42e64e\n");
printf(" nt_par_err = 1011\n\n");
printf("\n expected outcome:\n");
printf(" KEY 0xFFFFFFFFFFFF == fa247164 fb47c594 0000 71909d28 0c254817 1000 0dc7cfbd 1110\n");
return 1;
}
int main(int argc, char *argv[]) {
printf("Mifare classic nested auth key recovery. Phase 1.\n");
if (argc < 9) return usage();
sscanf(argv[1], "%x", &uid);
sscanf(argv[2], "%x", &nt_enc);
sscanf(argv[3], "%x", &nt_par_err);
sscanf(argv[4], "%x", &nr_enc);
sscanf(argv[5], "%x", &ar_enc);
sscanf(argv[6], "%x", &ar_par_err);
sscanf(argv[7], "%x", &at_enc);
sscanf(argv[8], "%x", &at_par_err);
if (argc > 9)
sscanf(argv[9], "%x", &cmd_enc);
printf("-------------------------------------------------\n");
printf("uid:\t\t%08x\n", uid);
printf("nt encrypted:\t%08x\n", nt_enc);
printf("nt parity err:\t%04x\n", nt_par_err);
printf("nr encrypted:\t%08x\n", nr_enc);
printf("ar encrypted:\t%08x\n", ar_enc);
printf("ar parity err:\t%04x\n", ar_par_err);
printf("at encrypted:\t%08x\n", at_enc);
printf("at parity err:\t%04x\n", at_par_err);
if (argc > 9)
printf("next cmd enc:\t%08x\n\n", cmd_enc);
clock_t t1 = clock();
uint16_t nt_par = parity_from_err(nt_enc, nt_par_err);
uint16_t ar_par = parity_from_err(ar_enc, ar_par_err);
uint16_t at_par = parity_from_err(at_enc, at_par_err);
//calc (parity XOR corresponding nonce bit encoded with the same keystream bit)
uint16_t xored = xored_bits(nt_par, nt_enc, ar_par, ar_enc, at_par, at_enc);
#ifndef __WIN32
thread_count = sysconf(_SC_NPROCESSORS_CONF);
if (thread_count < 2)
thread_count = 2;
#endif /* _WIN32 */
printf("\nBruteforce using %zu threads to find encrypted tagnonce last bytes\n", thread_count);
pthread_t threads[thread_count];
// create a mutex to avoid interlacing print commands from our different threads
pthread_mutex_init(&print_lock, NULL);
// one thread T0 for none EV1.
struct thread_args *a = malloc(sizeof(struct thread_args));
a->xored = xored;
a->thread = 0;
a->idx = 0;
a->ev1 = false;
pthread_create(&threads[0], NULL, brute_thread, (void *)a);
// the rest of available threads to EV1 scenario
for (int i = 0; i < thread_count - 1; ++i) {
struct thread_args *b = malloc(sizeof(struct thread_args));
b->xored = xored;
b->thread = i + 1;
b->idx = i;
b->ev1 = true;
pthread_create(&threads[i + 1], NULL, brute_thread, (void *)b);
}
// wait for threads to terminate:
for (int i = 0; i < thread_count; ++i)
pthread_join(threads[i], NULL);
if (!global_found && !global_found_candidate) {
printf("\nFailed to find a key\n\n");
}
t1 = clock() - t1;
if (t1 > 0)
printf("Execution time: %.0f ticks\n", (float)t1);
// clean up mutex
pthread_mutex_destroy(&print_lock);
return 0;
}

View file

@ -0,0 +1,20 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
#define ISO14443A_CMD_READBLOCK 0x30
#define ISO14443A_CMD_WRITEBLOCK 0xA0
#define MIFARE_AUTH_KEYA 0x60
#define MIFARE_AUTH_KEYB 0x61
#define MIFARE_CMD_INC 0xC0
#define MIFARE_CMD_DEC 0xC1
#define MIFARE_CMD_RESTORE 0xC2
#define MIFARE_CMD_TRANSFER 0xB0
// mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK
#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed)
#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error
#endif
// PROTOCOL_H

View file

@ -0,0 +1,28 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// platform-independant sleep macros
//-----------------------------------------------------------------------------
#ifndef _WIN32
#define _POSIX_C_SOURCE 199309L
#include "sleep.h"
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
void nsleep(uint64_t n) {
struct timespec timeout;
timeout.tv_sec = n / 1000000000;
timeout.tv_nsec = n % 1000000000;
while (nanosleep(&timeout, &timeout) && errno == EINTR);
}
#endif // _WIN32

View file

@ -0,0 +1,27 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// platform-independant sleep macros
//-----------------------------------------------------------------------------
#ifndef SLEEP_H__
#define SLEEP_H__
#ifdef _WIN32
# include <windows.h>
# define sleep(n) Sleep(1000 * n)
# define msleep(n) Sleep(n)
#else
# include <inttypes.h>
# include <unistd.h>
void nsleep(uint64_t n);
# define msleep(n) nsleep(1000000 * n)
# define usleep(n) nsleep(1000 * n)
#endif // _WIN32
#endif // SLEEP_H__