mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Merge branch 'master' into smartcard-relay
This commit is contained in:
commit
efea49415d
13 changed files with 206 additions and 58 deletions
|
@ -139,7 +139,7 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
|
||||||
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
||||||
}
|
}
|
||||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
||||||
return mifare_classic_authex_cmd(pcs, uid, blockNo, keyType ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing);
|
return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) == 0 ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing);
|
||||||
}
|
}
|
||||||
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ THE SOFTWARE.
|
||||||
#define DEBUG_KEY_ELIMINATION 1
|
#define DEBUG_KEY_ELIMINATION 1
|
||||||
// #define DEBUG_BRUTE_FORCE
|
// #define DEBUG_BRUTE_FORCE
|
||||||
|
|
||||||
|
#define MIN_BUCKETS_SIZE 128
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EVEN_STATE = 0,
|
EVEN_STATE = 0,
|
||||||
ODD_STATE = 1
|
ODD_STATE = 1
|
||||||
|
@ -88,7 +90,8 @@ static uint32_t bf_test_nonce[256];
|
||||||
static uint8_t bf_test_nonce_2nd_byte[256];
|
static uint8_t bf_test_nonce_2nd_byte[256];
|
||||||
static uint8_t bf_test_nonce_par[256];
|
static uint8_t bf_test_nonce_par[256];
|
||||||
static uint32_t bucket_count = 0;
|
static uint32_t bucket_count = 0;
|
||||||
static statelist_t *buckets[128];
|
static size_t buckets_allocated = 0;
|
||||||
|
static statelist_t **buckets = NULL;
|
||||||
static uint32_t keys_found = 0;
|
static uint32_t keys_found = 0;
|
||||||
static uint64_t num_keys_tested;
|
static uint64_t num_keys_tested;
|
||||||
static uint64_t found_bs_key = 0;
|
static uint64_t found_bs_key = 0;
|
||||||
|
@ -157,6 +160,7 @@ crack_states_thread(void *x) {
|
||||||
uint8_t *best_first_bytes;
|
uint8_t *best_first_bytes;
|
||||||
} *thread_arg;
|
} *thread_arg;
|
||||||
|
|
||||||
|
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
|
||||||
thread_arg = (struct arg *)x;
|
thread_arg = (struct arg *)x;
|
||||||
const int thread_id = thread_arg->thread_ID;
|
const int thread_id = thread_arg->thread_ID;
|
||||||
uint32_t current_bucket = thread_id;
|
uint32_t current_bucket = thread_id;
|
||||||
|
@ -188,7 +192,7 @@ crack_states_thread(void *x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_bucket += NUM_BRUTE_FORCE_THREADS;
|
current_bucket += num_brute_force_threads;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -294,12 +298,34 @@ static void write_benchfile(statelist_t *candidates) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static bool ensure_buckets_alloc(size_t need_buckets) {
|
||||||
|
if (need_buckets > buckets_allocated) {
|
||||||
|
size_t alloc_sz = ((buckets_allocated == 0) ? MIN_BUCKETS_SIZE : (buckets_allocated * 2));
|
||||||
|
while (need_buckets > alloc_sz) {
|
||||||
|
alloc_sz *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz);
|
||||||
|
if (buckets == NULL) {
|
||||||
|
buckets_allocated = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(buckets + buckets_allocated, 0, (alloc_sz - buckets_allocated) * sizeof(statelist_t *));
|
||||||
|
buckets_allocated = alloc_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) {
|
bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) {
|
||||||
#if defined (WRITE_BENCH_FILE)
|
#if defined (WRITE_BENCH_FILE)
|
||||||
write_benchfile(candidates);
|
write_benchfile(candidates);
|
||||||
#endif
|
#endif
|
||||||
bool silent = (bf_rate != NULL);
|
bool silent = (bf_rate != NULL);
|
||||||
|
|
||||||
|
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
|
||||||
|
|
||||||
keys_found = 0;
|
keys_found = 0;
|
||||||
num_keys_tested = 0;
|
num_keys_tested = 0;
|
||||||
found_bs_key = 0;
|
found_bs_key = 0;
|
||||||
|
@ -310,6 +336,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
bucket_count = 0;
|
bucket_count = 0;
|
||||||
for (statelist_t *p = candidates; p != NULL; p = p->next) {
|
for (statelist_t *p = candidates; p != NULL; p = p->next) {
|
||||||
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) {
|
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) {
|
||||||
|
if (!ensure_buckets_alloc(bucket_count + 1)) {
|
||||||
|
PrintAndLogEx(ERR, "Can't allocate buckets, abort!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
buckets[bucket_count] = p;
|
buckets[bucket_count] = p;
|
||||||
bucket_count++;
|
bucket_count++;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +353,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pthread_t threads[NUM_BRUTE_FORCE_THREADS];
|
pthread_t threads[num_brute_force_threads];
|
||||||
struct args {
|
struct args {
|
||||||
bool silent;
|
bool silent;
|
||||||
int thread_ID;
|
int thread_ID;
|
||||||
|
@ -331,9 +362,9 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
uint64_t maximum_states;
|
uint64_t maximum_states;
|
||||||
noncelist_t *nonces;
|
noncelist_t *nonces;
|
||||||
uint8_t *best_first_bytes;
|
uint8_t *best_first_bytes;
|
||||||
} thread_args[NUM_BRUTE_FORCE_THREADS];
|
} thread_args[num_brute_force_threads];
|
||||||
|
|
||||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) {
|
for (uint32_t i = 0; i < num_brute_force_threads; i++) {
|
||||||
thread_args[i].thread_ID = i;
|
thread_args[i].thread_ID = i;
|
||||||
thread_args[i].silent = silent;
|
thread_args[i].silent = silent;
|
||||||
thread_args[i].cuid = cuid;
|
thread_args[i].cuid = cuid;
|
||||||
|
@ -343,10 +374,14 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||||
thread_args[i].best_first_bytes = best_first_bytes;
|
thread_args[i].best_first_bytes = best_first_bytes;
|
||||||
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]);
|
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]);
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) {
|
for (uint32_t i = 0; i < num_brute_force_threads; i++) {
|
||||||
pthread_join(threads[i], 0);
|
pthread_join(threads[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buckets);
|
||||||
|
buckets = NULL;
|
||||||
|
buckets_allocated = 0;
|
||||||
|
|
||||||
uint64_t elapsed_time = msclock() - start_time;
|
uint64_t elapsed_time = msclock() - start_time;
|
||||||
|
|
||||||
if (bf_rate != NULL)
|
if (bf_rate != NULL)
|
||||||
|
@ -434,30 +469,31 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
||||||
|
|
||||||
|
|
||||||
float brute_force_benchmark(void) {
|
float brute_force_benchmark(void) {
|
||||||
statelist_t test_candidates[NUM_BRUTE_FORCE_THREADS];
|
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
|
||||||
|
statelist_t test_candidates[num_brute_force_threads];
|
||||||
|
|
||||||
test_candidates[0].states[ODD_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
|
test_candidates[0].states[ODD_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
|
||||||
test_candidates[0].states[EVEN_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
|
test_candidates[0].states[EVEN_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t));
|
||||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS - 1; i++) {
|
for (uint32_t i = 0; i < num_brute_force_threads - 1; i++) {
|
||||||
test_candidates[i].next = test_candidates + i + 1;
|
test_candidates[i].next = test_candidates + i + 1;
|
||||||
test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE];
|
test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE];
|
||||||
test_candidates[i + 1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE];
|
test_candidates[i + 1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE];
|
||||||
}
|
}
|
||||||
test_candidates[NUM_BRUTE_FORCE_THREADS - 1].next = NULL;
|
test_candidates[num_brute_force_threads - 1].next = NULL;
|
||||||
|
|
||||||
if (!read_bench_data(test_candidates)) {
|
if (!read_bench_data(test_candidates)) {
|
||||||
PrintAndLogEx(NORMAL, "Couldn't read benchmark data. Assuming brute force rate of %1.0f states per second", DEFAULT_BRUTE_FORCE_RATE);
|
PrintAndLogEx(NORMAL, "Couldn't read benchmark data. Assuming brute force rate of %1.0f states per second", DEFAULT_BRUTE_FORCE_RATE);
|
||||||
return DEFAULT_BRUTE_FORCE_RATE;
|
return DEFAULT_BRUTE_FORCE_RATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) {
|
for (uint32_t i = 0; i < num_brute_force_threads; i++) {
|
||||||
test_candidates[i].len[ODD_STATE] = TEST_BENCH_SIZE;
|
test_candidates[i].len[ODD_STATE] = TEST_BENCH_SIZE;
|
||||||
test_candidates[i].len[EVEN_STATE] = TEST_BENCH_SIZE;
|
test_candidates[i].len[EVEN_STATE] = TEST_BENCH_SIZE;
|
||||||
test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1;
|
test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1;
|
||||||
test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1;
|
test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)NUM_BRUTE_FORCE_THREADS;
|
uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)num_brute_force_threads;
|
||||||
|
|
||||||
float bf_rate;
|
float bf_rate;
|
||||||
uint64_t found_key = 0;
|
uint64_t found_key = 0;
|
||||||
|
|
|
@ -57,6 +57,11 @@
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"value": "6a02c3020602ffff",
|
||||||
|
"name": "Access: Hotel: Hilton",
|
||||||
|
"description": "TCI might be a wildcard before a reservation is made"
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"value": "6a02cb0206021100deadbeefdeadbeef",
|
"value": "6a02cb0206021100deadbeefdeadbeef",
|
||||||
|
@ -64,10 +69,45 @@
|
||||||
"description": "Last 8 bytes refer to reader group identifier, common for all readers in same home installation, allows to differentiate between keys for different homes"
|
"description": "Last 8 bytes refer to reader group identifier, common for all readers in same home installation, allows to differentiate between keys for different homes"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010001",
|
||||||
|
"name": "Access: Car Pairing: BMW",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for BMW"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"value": "6a02c30209010201",
|
"value": "6a02c30209010201",
|
||||||
"name": "Access: Mercedes Pairing",
|
"name": "Access: Car Pairing: Mercedes",
|
||||||
"description": "Device does not respond to this frame. Displays a car pairing popup for Mercedes"
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for Mercedes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010051",
|
||||||
|
"name": "Access: Car Pairing: Genesis",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for Genesis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010041",
|
||||||
|
"name": "Access: Car Pairing: KIA",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for KIA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010301",
|
||||||
|
"name": "Access: Car Pairing: Hyundai",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for Hyundai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010701",
|
||||||
|
"name": "Access: Car Pairing: BYD",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for BYD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010241",
|
||||||
|
"name": "Access: Car Pairing: Denza",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for Denza"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "6a02c30209010091",
|
||||||
|
"name": "Access: Car Pairing: Lotus",
|
||||||
|
"description": "Device does not respond to poll after this frame. Displays a car pairing popup for Lotus"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2241,28 +2241,29 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
|
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect MFC EV1 Signature
|
if (g_session.pm3_present && !tests) {
|
||||||
if (detect_mfc_ev1_signature() && keylen == 0) {
|
// detect MFC EV1 Signature
|
||||||
PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
|
if (detect_mfc_ev1_signature() && keylen == 0) {
|
||||||
blockno = 69;
|
PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
|
||||||
keytype = MF_KEY_B;
|
blockno = 69;
|
||||||
memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
|
keytype = MF_KEY_B;
|
||||||
}
|
memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
|
||||||
|
|
||||||
if (known_target_key == false && nonce_file_read == false) {
|
|
||||||
|
|
||||||
// check if tag doesn't have static nonce
|
|
||||||
if (detect_classic_static_nonce() == NONCE_STATIC) {
|
|
||||||
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
|
|
||||||
PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
|
|
||||||
return PM3_EOPABORTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t key64 = 0;
|
if (known_target_key == false && nonce_file_read == false) {
|
||||||
// check if we can authenticate to sector
|
// check if tag doesn't have static nonce
|
||||||
if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) {
|
if (detect_classic_static_nonce() == NONCE_STATIC) {
|
||||||
PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A');
|
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
|
||||||
return PM3_EWRONGANSWER;
|
PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
|
||||||
|
return PM3_EOPABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t key64 = 0;
|
||||||
|
// check if we can authenticate to sector
|
||||||
|
if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A');
|
||||||
|
return PM3_EWRONGANSWER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
|
|
||||||
#define STATE_FILES_DIRECTORY "hardnested_tables/"
|
#define STATE_FILES_DIRECTORY "hardnested_tables/"
|
||||||
#define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.bz2"
|
#define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.bz2"
|
||||||
|
#define STATE_FILE_TEMPLATE_RAW "bitflip_%d_%03" PRIx16 "_states.bin"
|
||||||
|
|
||||||
#define DEBUG_KEY_ELIMINATION
|
#define DEBUG_KEY_ELIMINATION
|
||||||
// #define DEBUG_REDUCTION
|
// #define DEBUG_REDUCTION
|
||||||
|
@ -260,10 +261,13 @@ static void init_bitflip_bitarrays(void) {
|
||||||
|
|
||||||
char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + strlen(STATE_FILE_TEMPLATE) + 1];
|
char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + strlen(STATE_FILE_TEMPLATE) + 1];
|
||||||
char state_file_name[strlen(STATE_FILE_TEMPLATE) + 1];
|
char state_file_name[strlen(STATE_FILE_TEMPLATE) + 1];
|
||||||
|
char state_file_raw_name[strlen(STATE_FILE_TEMPLATE_RAW) + 1];
|
||||||
|
|
||||||
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
||||||
num_effective_bitflips[odd_even] = 0;
|
num_effective_bitflips[odd_even] = 0;
|
||||||
for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) {
|
for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) {
|
||||||
|
bool open_uncompressed = false;
|
||||||
|
|
||||||
bitflip_bitarrays[odd_even][bitflip] = NULL;
|
bitflip_bitarrays[odd_even][bitflip] = NULL;
|
||||||
count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24;
|
count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24;
|
||||||
|
|
||||||
|
@ -273,14 +277,21 @@ static void init_bitflip_bitarrays(void) {
|
||||||
|
|
||||||
char *path;
|
char *path;
|
||||||
if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) != PM3_SUCCESS) {
|
if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) != PM3_SUCCESS) {
|
||||||
continue;
|
snprintf(state_file_raw_name, sizeof(state_file_raw_name), STATE_FILE_TEMPLATE_RAW, odd_even, bitflip);
|
||||||
|
strncpy(state_files_path, STATE_FILES_DIRECTORY, sizeof(state_files_path) - 1);
|
||||||
|
strncat(state_files_path, state_file_raw_name, sizeof(state_files_path) - (strlen(STATE_FILES_DIRECTORY) + 1));
|
||||||
|
if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) == PM3_SUCCESS) {
|
||||||
|
open_uncompressed = true;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *statesfile = fopen(path, "rb");
|
FILE *statesfile = fopen(path, "rb");
|
||||||
free(path);
|
free(path);
|
||||||
if (statesfile == NULL) {
|
if (statesfile == NULL) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else if (!open_uncompressed) {
|
||||||
fseek(statesfile, 0, SEEK_END);
|
fseek(statesfile, 0, SEEK_END);
|
||||||
int fsize = ftell(statesfile);
|
int fsize = ftell(statesfile);
|
||||||
if (fsize == -1) {
|
if (fsize == -1) {
|
||||||
|
@ -335,6 +346,52 @@ static void init_bitflip_bitarrays(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
BZ2_bzDecompressEnd(&compressed_stream);
|
BZ2_bzDecompressEnd(&compressed_stream);
|
||||||
|
} else {
|
||||||
|
fseek(statesfile, 0, SEEK_END);
|
||||||
|
int fsize = ftell(statesfile);
|
||||||
|
if (fsize == -1) {
|
||||||
|
PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name);
|
||||||
|
fclose(statesfile);
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
uint32_t filesize = (uint32_t)fsize;
|
||||||
|
rewind(statesfile);
|
||||||
|
|
||||||
|
uint32_t count = 0;
|
||||||
|
size_t bytesread = fread(&count, 1, sizeof(count), statesfile);
|
||||||
|
if (bytesread != 4) {
|
||||||
|
PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name);
|
||||||
|
fclose(statesfile);
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((float)count / (1 << 24) < IGNORE_BITFLIP_THRESHOLD) {
|
||||||
|
uint32_t *bitset = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1 << 19));
|
||||||
|
if (bitset == NULL) {
|
||||||
|
PrintAndLogEx(ERR, "Out of memory error in init_bitflip_statelists(). Aborting...\n");
|
||||||
|
fclose(statesfile);
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesread = fread(bitset, 1, filesize-sizeof(count), statesfile);
|
||||||
|
if (bytesread != filesize-sizeof(count)) {
|
||||||
|
PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name);
|
||||||
|
fclose(statesfile);
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
effective_bitflip[odd_even][num_effective_bitflips[odd_even]++] = bitflip;
|
||||||
|
bitflip_bitarrays[odd_even][bitflip] = bitset;
|
||||||
|
count_bitflip_bitarrays[odd_even][bitflip] = count;
|
||||||
|
#if defined (DEBUG_REDUCTION)
|
||||||
|
PrintAndLogEx(INFO, "(%03" PRIx16 " %s:%5.1f%%) ", bitflip, odd_even ? "odd " : "even", (float)count / (1 << 24) * 100.0);
|
||||||
|
line++;
|
||||||
|
if (line == 8) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
line = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
effective_bitflip[odd_even][num_effective_bitflips[odd_even]] = 0x400; // EndOfList marker
|
effective_bitflip[odd_even][num_effective_bitflips[odd_even]] = 0x400; // EndOfList marker
|
||||||
|
@ -1223,31 +1280,32 @@ __attribute__((force_align_arg_pointer))
|
||||||
|
|
||||||
static void check_for_BitFlipProperties(bool time_budget) {
|
static void check_for_BitFlipProperties(bool time_budget) {
|
||||||
// create and run worker threads
|
// create and run worker threads
|
||||||
pthread_t thread_id[NUM_CHECK_BITFLIPS_THREADS];
|
const size_t num_check_bitflip_threads = NUM_CHECK_BITFLIPS_THREADS;
|
||||||
|
pthread_t thread_id[num_check_bitflip_threads];
|
||||||
|
|
||||||
uint8_t args[NUM_CHECK_BITFLIPS_THREADS][3];
|
uint8_t args[num_check_bitflip_threads][3];
|
||||||
uint16_t bytes_per_thread = (256 + (NUM_CHECK_BITFLIPS_THREADS / 2)) / NUM_CHECK_BITFLIPS_THREADS;
|
uint16_t bytes_per_thread = (256 + (num_check_bitflip_threads / 2)) / num_check_bitflip_threads;
|
||||||
for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) {
|
for (uint32_t i = 0; i < num_check_bitflip_threads; i++) {
|
||||||
args[i][0] = i * bytes_per_thread;
|
args[i][0] = i * bytes_per_thread;
|
||||||
args[i][1] = MIN(args[i][0] + bytes_per_thread - 1, 255);
|
args[i][1] = MIN(args[i][0] + bytes_per_thread - 1, 255);
|
||||||
args[i][2] = time_budget;
|
args[i][2] = time_budget;
|
||||||
}
|
}
|
||||||
// args[][] is uint8_t so max 255, no need to check it
|
// args[][] is uint8_t so max 255, no need to check it
|
||||||
// args[NUM_CHECK_BITFLIPS_THREADS - 1][1] = MAX(args[NUM_CHECK_BITFLIPS_THREADS - 1][1], 255);
|
// args[num_check_bitflip_threads - 1][1] = MAX(args[num_check_bitflip_threads - 1][1], 255);
|
||||||
|
|
||||||
// start threads
|
// start threads
|
||||||
for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) {
|
for (uint32_t i = 0; i < num_check_bitflip_threads; i++) {
|
||||||
pthread_create(&thread_id[i], NULL, check_for_BitFlipProperties_thread, args[i]);
|
pthread_create(&thread_id[i], NULL, check_for_BitFlipProperties_thread, args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for threads to terminate:
|
// wait for threads to terminate:
|
||||||
for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) {
|
for (uint32_t i = 0; i < num_check_bitflip_threads; i++) {
|
||||||
pthread_join(thread_id[i], NULL);
|
pthread_join(thread_id[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hardnested_stage & CHECK_2ND_BYTES) {
|
if (hardnested_stage & CHECK_2ND_BYTES) {
|
||||||
hardnested_stage &= ~CHECK_1ST_BYTES; // we are done with 1st stage, except...
|
hardnested_stage &= ~CHECK_1ST_BYTES; // we are done with 1st stage, except...
|
||||||
for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) {
|
for (uint32_t i = 0; i < num_check_bitflip_threads; i++) {
|
||||||
if (args[i][1] != 0) {
|
if (args[i][1] != 0) {
|
||||||
hardnested_stage |= CHECK_1ST_BYTES; // ... when any of the threads didn't complete in time
|
hardnested_stage |= CHECK_1ST_BYTES; // ... when any of the threads didn't complete in time
|
||||||
break;
|
break;
|
||||||
|
@ -2057,10 +2115,11 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) {
|
||||||
init_book_of_work();
|
init_book_of_work();
|
||||||
|
|
||||||
// create and run worker threads
|
// create and run worker threads
|
||||||
pthread_t thread_id[NUM_REDUCTION_WORKING_THREADS];
|
const size_t num_reduction_working_threads = NUM_REDUCTION_WORKING_THREADS;
|
||||||
|
pthread_t thread_id[num_reduction_working_threads];
|
||||||
|
|
||||||
uint16_t sums1[NUM_REDUCTION_WORKING_THREADS][3];
|
uint16_t sums1[num_reduction_working_threads][3];
|
||||||
for (uint32_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) {
|
for (uint32_t i = 0; i < num_reduction_working_threads; i++) {
|
||||||
sums1[i][0] = sum_a0_idx;
|
sums1[i][0] = sum_a0_idx;
|
||||||
sums1[i][1] = sum_a8_idx;
|
sums1[i][1] = sum_a8_idx;
|
||||||
sums1[i][2] = i + 1;
|
sums1[i][2] = i + 1;
|
||||||
|
@ -2068,7 +2127,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for threads to terminate:
|
// wait for threads to terminate:
|
||||||
for (uint32_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) {
|
for (uint32_t i = 0; i < num_reduction_working_threads; i++) {
|
||||||
pthread_join(thread_id[i], NULL);
|
pthread_join(thread_id[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -621,9 +621,7 @@ bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int
|
||||||
// check if we can communicate with Pm3
|
// check if we can communicate with Pm3
|
||||||
int TestProxmark(pm3_device_t *dev) {
|
int TestProxmark(pm3_device_t *dev) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
|
||||||
uint16_t len = 32;
|
uint16_t len = 32;
|
||||||
bool is_tcp_conn = false;
|
|
||||||
uint8_t data[len];
|
uint8_t data[len];
|
||||||
for (uint16_t i = 0; i < len; i++)
|
for (uint16_t i = 0; i < len; i++)
|
||||||
data[i] = i & 0xFF;
|
data[i] = i & 0xFF;
|
||||||
|
@ -643,6 +641,7 @@ int TestProxmark(pm3_device_t *dev) {
|
||||||
timeout = 1000;
|
timeout = 1000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) {
|
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) {
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -666,12 +665,15 @@ int TestProxmark(pm3_device_t *dev) {
|
||||||
memcpy(&g_pm3_capabilities, resp.data.asBytes, MIN(sizeof(capabilities_t), resp.length));
|
memcpy(&g_pm3_capabilities, resp.data.asBytes, MIN(sizeof(capabilities_t), resp.length));
|
||||||
g_conn.send_via_fpc_usart = g_pm3_capabilities.via_fpc;
|
g_conn.send_via_fpc_usart = g_pm3_capabilities.via_fpc;
|
||||||
g_conn.uart_speed = g_pm3_capabilities.baudrate;
|
g_conn.uart_speed = g_pm3_capabilities.baudrate;
|
||||||
is_tcp_conn = memcmp(g_conn.serial_port_name, "tcp:", 4) == 0;
|
|
||||||
|
bool is_tcp_conn = (memcmp(g_conn.serial_port_name, "tcp:", 4) == 0);
|
||||||
|
bool is_bt_conn = (memcmp(g_conn.serial_port_name, "bt:", 3) == 0);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Communicating with PM3 over %s%s%s",
|
PrintAndLogEx(INFO, "Communicating with PM3 over %s%s%s",
|
||||||
g_conn.send_via_fpc_usart ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"),
|
(g_conn.send_via_fpc_usart) ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"),
|
||||||
is_tcp_conn ? " over " _YELLOW_("TCP") : "",
|
(is_tcp_conn) ? " over " _YELLOW_("TCP") : "",
|
||||||
memcmp(g_conn.serial_port_name, "bt:", 3) == 0 ? " over " _YELLOW_("BT") : "");
|
(is_bt_conn) ? " over " _YELLOW_("BT") : ""
|
||||||
|
);
|
||||||
|
|
||||||
if (g_conn.send_via_fpc_usart) {
|
if (g_conn.send_via_fpc_usart) {
|
||||||
PrintAndLogEx(INFO, "PM3 UART serial baudrate: " _YELLOW_("%u") "\n", g_conn.uart_speed);
|
PrintAndLogEx(INFO, "PM3 UART serial baudrate: " _YELLOW_("%u") "\n", g_conn.uart_speed);
|
||||||
|
@ -771,7 +773,6 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms
|
||||||
|
|
||||||
if (msclock() - tmp_clk > 3000 && show_warning) {
|
if (msclock() - tmp_clk > 3000 && show_warning) {
|
||||||
// 3 seconds elapsed (but this doesn't mean the timeout was exceeded)
|
// 3 seconds elapsed (but this doesn't mean the timeout was exceeded)
|
||||||
// PrintAndLogEx(INFO, "Waiting for a response from the Proxmark3...");
|
|
||||||
PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button");
|
PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button");
|
||||||
show_warning = false;
|
show_warning = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,12 +268,20 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo
|
||||||
*validLong = false;
|
*validLong = false;
|
||||||
uint8_t bLen = isLong ? 110 : 55;
|
uint8_t bLen = isLong ? 110 : 55;
|
||||||
uint16_t parityCol[4] = { 0, 0, 0, 0 };
|
uint16_t parityCol[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
for (int word = 0; word < bLen; word += 5) {
|
for (int word = 0; word < bLen; word += 5) {
|
||||||
for (int bit = 0; bit < 5; bit++) {
|
for (int bit = 0; bit < 5; bit++) {
|
||||||
if (word + bit >= bLen) break;
|
|
||||||
|
if (word + bit >= bLen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
parityWd = (parityWd << 1) | bits[startIdx + word + bit];
|
parityWd = (parityWd << 1) | bits[startIdx + word + bit];
|
||||||
if ((word <= 50) && (bit < 4))
|
|
||||||
|
if ((word <= 50) && (bit < 4)) {
|
||||||
parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
|
parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
|
||||||
|
}
|
||||||
|
|
||||||
bits[bitCnt++] = (bits[startIdx + word + bit]);
|
bits[bitCnt++] = (bits[startIdx + word + bit]);
|
||||||
}
|
}
|
||||||
if (word + 5 > bLen) break;
|
if (word + 5 > bLen) break;
|
||||||
|
@ -293,12 +301,15 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo
|
||||||
if (!isLong && validRowParitySkipColP && validColParity) {
|
if (!isLong && validRowParitySkipColP && validColParity) {
|
||||||
*validShort = true;
|
*validShort = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLong && validRowParity) {
|
if (isLong && validRowParity) {
|
||||||
*validLong = true;
|
*validLong = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLong && validRowParitySkipColP && validColParity) {
|
if (isLong && validRowParitySkipColP && validColParity) {
|
||||||
*validShortExtended = true;
|
*validShortExtended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*validShort || *validShortExtended || *validLong) {
|
if (*validShort || *validShortExtended || *validLong) {
|
||||||
return bitCnt;
|
return bitCnt;
|
||||||
} else {
|
} else {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -221,7 +221,7 @@ reg curbit;
|
||||||
`ifdef PM3ICOPYX
|
`ifdef PM3ICOPYX
|
||||||
`define EDGE_DETECT_THRESHOLD 3
|
`define EDGE_DETECT_THRESHOLD 3
|
||||||
`else
|
`else
|
||||||
`define EDGE_DETECT_THRESHOLD 5
|
`define EDGE_DETECT_THRESHOLD 7
|
||||||
`endif
|
`endif
|
||||||
`define EDGE_DETECT_THRESHOLDHIGH 20
|
`define EDGE_DETECT_THRESHOLDHIGH 20
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue