MFOC patches have now been ported upstream

This commit is contained in:
Philippe Teuwen
2017-02-17 16:23:43 +01:00
parent 39658a2ac4
commit 137680aee9
5 changed files with 1 additions and 352 deletions
-13
View File
@@ -1,13 +0,0 @@
diff --git a/src/mfoc.c b/src/mfoc.c
index 32ef6f7..babbe15 100644
--- a/src/mfoc.c
+++ b/src/mfoc.c
@@ -756,7 +756,7 @@ int main(int argc, char *const argv[])
}
// Finally save all keys + data to file
- uint16_t dump_size = (t.num_blocks + 1) * t.num_sectors;
+ uint16_t dump_size = (t.num_blocks + 1) * 16;
if (fwrite(&mtDump, 1, dump_size, pfDump) != dump_size) {
fprintf(stdout, "Error, cannot write dump\n");
fclose(pfDump);
-153
View File
@@ -1,153 +0,0 @@
diff --git a/src/mfoc.c b/src/mfoc.c
index 469b138..ba11ce9 100644
--- a/src/mfoc.c
+++ b/src/mfoc.c
@@ -56,6 +56,13 @@
#include "slre.h"
#include "slre.c"
+#define MAX_FRAME_LEN 264
+
+static const nfc_modulation nm = {
+.nmt = NMT_ISO14443A,
+.nbr = NBR_106,
+};
+
nfc_context *context;
uint64_t knownKey = 0;
@@ -99,13 +106,8 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
return(-99999);
}
-
int main(int argc, char *const argv[])
{
- const nfc_modulation nm = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106,
- };
int ch, i, k, n, j, m;
int key, block;
@@ -321,9 +323,15 @@ int main(int argc, char *const argv[])
case 0x01:
case 0x08:
case 0x88:
- printf("Found Mifare Classic 1k tag\n");
- t.num_sectors = NR_TRAILERS_1k;
- t.num_blocks = NR_BLOCKS_1k;
+ if (get_rats_is_2k(t, r)) {
+ printf("Found Mifare Plus 2k tag\n");
+ t.num_sectors = NR_TRAILERS_2k;
+ t.num_blocks = NR_BLOCKS_2k;
+ } else {
+ printf("Found Mifare Classic 1k tag\n");
+ t.num_sectors = NR_TRAILERS_1k;
+ t.num_blocks = NR_BLOCKS_1k;
+ }
break;
case 0x09:
printf("Found Mifare Classic Mini tag\n");
@@ -858,11 +866,6 @@ void mf_configure(nfc_device *pdi)
void mf_select_tag(nfc_device *pdi, nfc_target *pnt)
{
- // Poll for a ISO14443A (MIFARE) tag
- const nfc_modulation nm = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106,
- };
if (nfc_initiator_select_passive_target(pdi, nm, NULL, 0, pnt) < 0) {
ERR("Unable to connect to the MIFARE Classic tag");
nfc_close(pdi);
@@ -905,10 +908,6 @@ int find_exploit_sector(mftag t)
void mf_anticollision(mftag t, mfreader r)
{
- const nfc_modulation nm = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106,
- };
if (nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt) < 0) {
nfc_perror(r.pdi, "nfc_initiator_select_passive_target");
ERR("Tag has been removed");
@@ -916,6 +915,48 @@ void mf_anticollision(mftag t, mfreader r)
}
}
+
+bool
+get_rats_is_2k(mftag t, mfreader r)
+{
+ int res;
+ uint8_t abtRx[MAX_FRAME_LEN];
+ int szRxBits;
+ uint8_t abtRats[2] = { 0xe0, 0x50};
+ // Use raw send/receive methods
+ if (nfc_device_set_property_bool(r.pdi, NP_EASY_FRAMING, false) < 0) {
+ nfc_perror(r.pdi, "nfc_configure");
+ return false;
+ }
+ res = nfc_initiator_transceive_bytes(r.pdi, abtRats, sizeof(abtRats), abtRx, sizeof(abtRx), 0);
+ if (res > 0) {
+ // ISO14443-4 card, turn RF field off/on to access ISO14443-3 again
+ if (nfc_device_set_property_bool(r.pdi, NP_ACTIVATE_FIELD, false) < 0) {
+ nfc_perror(r.pdi, "nfc_configure");
+ return false;
+ }
+ if (nfc_device_set_property_bool(r.pdi, NP_ACTIVATE_FIELD, true) < 0) {
+ nfc_perror(r.pdi, "nfc_configure");
+ return false;
+ }
+ }
+ // Reselect tag
+ if (nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt) <= 0) {
+ printf("Error: tag disappeared\n");
+ nfc_close(r.pdi);
+ nfc_exit(context);
+ exit(EXIT_FAILURE);
+ }
+ if (res >= 10) {
+ printf("ATS %02X%02X%02X%02X%02X|%02X%02X%02X%02X\n", res, abtRx[0], abtRx[1], abtRx[2], abtRx[3], abtRx[4], abtRx[5], abtRx[6], abtRx[7], abtRx[8]);
+ return ((abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
+ && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
+ && ((t.nt.nti.nai.abtAtqa[1] & 0x02) == 0x00));
+ } else {
+ return false;
+ }
+}
+
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA)
{
struct Crypto1State *pcs;
diff --git a/src/mfoc.h b/src/mfoc.h
index 532e834..9ea7547 100644
--- a/src/mfoc.h
+++ b/src/mfoc.h
@@ -8,6 +8,8 @@
#define NR_TRAILERS_MINI (5)
// Mifare Classic 4k 32x64b + 8*256b = 40
#define NR_TRAILERS_4k (40)
+// Mifare Classic 2k 32x64b
+#define NR_TRAILERS_2k (32)
// Number of blocks
// Mifare Classic 1k
@@ -16,6 +18,8 @@
#define NR_BLOCKS_MINI 0x13
// Mifare Classic 4k
#define NR_BLOCKS_4k 0xff
+// Mifare Classic 2k
+#define NR_BLOCKS_2k 0x7f
#define MAX_FRAME_LEN 264
@@ -85,6 +89,7 @@ void mf_select_tag(nfc_device *pdi, nfc_target *pnt);
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);
uint32_t median(denonce d);
int compar_int(const void *a, const void *b);
-21
View File
@@ -1,21 +0,0 @@
diff --git a/src/mfoc.c b/src/mfoc.c
index 2c06b16..469b138 100644
--- a/src/mfoc.c
+++ b/src/mfoc.c
@@ -307,7 +307,7 @@ int main(int argc, char *const argv[])
}
// Test if a compatible MIFARE tag is used
- if ((t.nt.nti.nai.btSak & 0x08) == 0) {
+ if (((t.nt.nti.nai.btSak & 0x08) == 0) && (t.nt.nti.nai.btSak != 0x01)) {
ERR("only Mifare Classic is supported");
goto error;
}
@@ -318,6 +318,7 @@ int main(int argc, char *const argv[])
// see http://www.nxp.com/documents/application_note/AN10833.pdf Section 3.2
switch (t.nt.nti.nai.btSak)
{
+ case 0x01:
case 0x08:
case 0x88:
printf("Found Mifare Classic 1k tag\n");
-160
View File
@@ -1,160 +0,0 @@
diff --git a/src/mfoc.c b/src/mfoc.c
index 32ef6f7..889669d 100644
--- a/src/mfoc.c
+++ b/src/mfoc.c
@@ -58,6 +58,48 @@
nfc_context *context;
+uint64_t knownKey = 0;
+char knownKeyLetter = 'A';
+uint32_t knownSector = 0;
+uint32_t unknownSector = 0;
+char unknownKeyLetter = 'A';
+uint32_t unexpected_random = 0;
+
+// Determine the distance between two nonces.
+// Assume that the difference is small, but we don't know which is first.
+// Therefore try in alternating directions.
+int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
+
+ if (nt1 == nt2) return 0;
+
+ uint16_t i;
+ uint32_t nttmp1 = nt1;
+ uint32_t nttmp2 = nt2;
+
+ for (i = 1; i < (32768/8); ++i) {
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -i;
+
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+1;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+1);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+2;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+2);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+3;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+3);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+4;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+4);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+5;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+5);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+6;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+6);
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+7;
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+7);
+ }
+ // either nt1 or nt2 are invalid nonces
+ return(-99999);
+}
+
+
int main(int argc, char *const argv[])
{
const nfc_modulation nm = {
@@ -117,6 +159,7 @@ int main(int argc, char *const argv[])
mifare_cmd mc;
FILE *pfDump = NULL;
+ FILE *pfKey = NULL;
//File pointers for the keyfile
FILE * fp;
@@ -200,6 +243,14 @@ int main(int argc, char *const argv[])
}
// fprintf(stdout, "Output file: %s\n", optarg);
break;
+ case 'D':
+ // Partial File output
+ if (!(pfKey = fopen(optarg, "w"))) {
+ fprintf(stderr, "Cannot open: %s, exiting\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ // fprintf(stdout, "Output file: %s\n", optarg);
+ break;
case 'h':
usage(stdout, 0);
break;
@@ -421,14 +472,28 @@ int main(int argc, char *const argv[])
fprintf(stdout, "\n");
for (i = 0; i < (t.num_sectors); ++i) {
- if(t.sectors[i].foundKeyA)
+ if(t.sectors[i].foundKeyA){
fprintf(stdout, "Sector %02d - Found Key A: %012llx ", i, bytes_to_num(t.sectors[i].KeyA, sizeof(t.sectors[i].KeyA)));
- else
+ memcpy(&knownKey, t.sectors[i].KeyA, 6);
+ knownKeyLetter = 'A';
+ knownSector = i;
+ }
+ else{
fprintf(stdout, "Sector %02d - Unknown Key A ", i);
- if(t.sectors[i].foundKeyB)
+ unknownSector = i;
+ unknownKeyLetter = 'A';
+ }
+ if(t.sectors[i].foundKeyB){
fprintf(stdout, "Found Key B: %012llx\n", bytes_to_num(t.sectors[i].KeyB, sizeof(t.sectors[i].KeyB)));
- else
+ knownKeyLetter = 'B';
+ memcpy(&knownKey, t.sectors[i].KeyB, 6);
+ knownSector = i;
+ }
+ else{
fprintf(stdout, "Unknown Key B\n");
+ unknownSector = i;
+ unknownKeyLetter = 'B';
+ }
}
fflush(stdout);
@@ -504,7 +569,18 @@ int main(int argc, char *const argv[])
// 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)
- mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA); // AUTH + Get Distances mode
+ 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, "%012llx;%d;%c;%d;%c", knownKey, knownSector, knownKeyLetter, unknownSector, unknownKeyLetter);
+ fclose(pfKey);
+ }
+ 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);
@@ -720,6 +796,7 @@ void usage(FILE *stream, int errno)
fprintf(stream, " T nonce tolerance half-range, instead of default of 20\n (i.e., 40 for the total range, in both directions)\n");
// fprintf(stream, " s specify the list of sectors to crack, for example -s 0,1,3,5\n");
fprintf(stream, " O file in which the card contents will be written (REQUIRED)\n");
+ fprintf(stream, " D file in which partial card info will be written in case PRNG is not vulnerable\n");
fprintf(stream, "\n");
fprintf(stream, "Example: mfoc -O mycard.mfd\n");
fprintf(stream, "Example: mfoc -k ffffeeeedddd -O mycard.mfd\n");
@@ -979,7 +1056,21 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// Save the determined nonces distance
d->distances[m] = nonce_distance(Nt, NtLast);
- // fprintf(stdout, "distance: %05d\n", d->distances[m]);
+ int checkForValidPRNG = dist_nt(Nt, NtLast);
+ //printf("NT distance: %d\n", checkForValidPRNG);
+
+ // if no distance between, then we are in sync.
+ if (checkForValidPRNG == 0) {
+ printf("NT Distance is zero..........\n");
+ } else {
+ if (checkForValidPRNG == -99999) { // invalid nonce received
+ ++unexpected_random;
+ if (unexpected_random > 4) {
+ printf("PRNG is not vulnerable to nested attack\n");
+ return -99999;
+ }
+ }
+ }
// Again, prepare and send {At}
for (i = 0; i < 4; i++) {
+1 -5
View File
@@ -12,11 +12,7 @@ sudo apt-get install git libnfc-bin autoconf libnfc-dev
cd mfoc || exit 1
git reset --hard
git clean -dfx
# patch initially done against commit 48156f9b:
patch -p1 < ../mfoc_test_prng.diff
patch -p1 < ../mfoc_fix_4k_and_mini.diff
patch -p1 < ../mfoc_support_tnp.diff
patch -p1 < ../mfoc_support_2k.diff
# tested against commit 9d9f01fb
autoreconf -vfi
./configure
make