MifareClassicTool icon indicating copy to clipboard operation
MifareClassicTool copied to clipboard

Key extraction from chinese sniffer cards

Open alfs opened this issue 8 years ago • 16 comments

There is a chinese sniffer card available (see http://www.proxmark.org/forum/viewtopic.php?id=1649 ) that logs the tag nonce and reader response, which can then be extracted and used for key recovery. Instead of the windows application tied to a specific NFC reader, it would be easier to use an app for key recovery instead.

I found that it's possible to use NfcA API to extract the needed information from the card by sending the raw commands, i.e.:

NfcA n = NfcA.get(tagFromIntent);
n.connect();
byte[] rats={(byte) 0xe0, 0x50}; // no checksum, (byte) 0xbc, (byte) 0xa5};
n.transceive(rats);
byte[] a={ 0x0a,  0x00,  0x00, (byte) 0xa6, (byte) 0xb0,  0x00,  0x10};
byte[] ar = n.transceive(a);
byte[] b={ 0x0b,  0x00,  0x00, (byte) 0xa6, (byte) 0xb0,  0x01,  0x10};
byte[] br  = n.transceive(b);

After DES-decrypting ar and br, getting the tag nonces and reader responses, key recovery can then be performed with the mfkey32 tool, or a java reimplementation.

Would this be an interesting/possible addition to MCT, or do you think it would be better as a separate app?

alfs avatar Jul 08 '15 23:07 alfs

Didnt that imp need the source exe from the Chinese tag application to be able to extract the mifare keys? That will be a big hurdle to overcome... if not all relevant bytes is extracted from the source exe, and ...

iceman1001 avatar Jul 09 '15 08:07 iceman1001

I started a standalone implementation. For the nonce table, I extracted a blob from the exe and put it as a raw resource (250 kb), and access/index it by

InputStream inStream = getResources().openRawResource(R.raw.table);
byte[] nonceTable = new byte[inStream.available()];
inStream.read(nonceTable);
nonce[0] = nonceTable[4*key+3]; 
// etc

DES deciphering was even more straightforward, e.g.

byte[] keyBytes = new byte[] { /* the key */ };
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding", "BC"); // /PKCS7Padding
cipher.init(Cipher.DECRYPT_MODE, key);
int ctLength = input.length;
plainText = new byte[cipher.getOutputSize(ctLength)];
int ptLength = cipher.update(input, 0, ctLength, plainText, 0);

The problem now is to port the crapto algorithm and mfkey to java, and it should be all set. I think it's all technically doable, but could be more questionable to publish an app in the play store containing the crypto1 code, and perhaps also the nonce blob.

In other news, my sniffer card also stopped working. It responds to RATS, but I cannot read the responses anymore, even with the proxmark. Just getting 6 bytes as response (0A 00 90 00 F3 93), where I previously got the bytes for des decryption. I have to try the original software to see if it does something more than RATS + magic read commands. [edit: nevermind - the sniffer card works fine, I got it mixed up with a normal magic clone card lying on my desk which obviously doesn't work]

alfs avatar Jul 09 '15 12:07 alfs

question is of course, if the supercard deals with tags with fixed prng or nack bug... if it does, i'm curious...

iceman1001 avatar Jul 09 '15 18:07 iceman1001

The sniffer card does not require a tag vulnerability, it attacks the reader. I.e. when the reader tries to read a sector on the sniffer card, it records it's tag challenge, the reader response and challege. With two reader authentication attempts, the key can be recovered (e.g. by the mfkey32 tool).

This can also be achieved with the proxmark hf mf sim x function, but it's much more convenient to use a card instead of lugging around a proxmark3 and surrounding equipment.

alfs avatar Jul 09 '15 20:07 alfs

not quite true. the mfkey32 works on tags with a bad prng. which is also how the hf mf sim x function works
so, my question still is unanswered

iceman1001 avatar Jul 09 '15 20:07 iceman1001

The sniffer card only has 2^16 different nonces (in the mapping table), which I guess are the vulnerable nonces (like hf mf sim x always chooses nonce 0x01 0x01 0x01 0x01 - and hf mf sim x is always able to extract the key, right?)

I've now also completed the key extraction app. Instead of converting crypto1/crapto1 and mfkey to native Java, I opted to include the C-code via JNI/NDK instead. It's at https://github.com/alfs/KeyExtractor if anyone is interested. It works fine on Galaxy S3, but not on Xperia Z3 where the special NfcA commands return garbage.

alfs avatar Jul 10 '15 02:07 alfs

no, the "HF MF SIM X" or mfkey32 is not always able to extract the key. It works on tags with bad prng. That issue has been fixed in newer tags. However, if you can extract other parts of the communication from the supercard to be able to use the mfkey64 tool that would be interesting to see how correct it is in breaking keys.

iceman1001 avatar Jul 11 '15 12:07 iceman1001

Sorry, I'm a bit confused. You say hf mf sim x only works on tags with bad prng, but as far as I know this command does not involve tags at all, so if they use a bad or good prng should not matter.

The sim x simulates a tag for the reader, and therefore proxmark has full control of the nonce (and simulates a bad prng with repeat nonces), it records the reader responses and runs them through mfkey to recover the key. Likewise the sniffer card controls the nonce, and the nonce, and responses are captured by the card for later extraction.

I don't see how the prng, or (legitimate) tags at all, are involved here. Or does the reader attack also depend on the randomness or answers by the card reader?

alfs avatar Jul 11 '15 13:07 alfs

true, the command simulates a tag, however the crypto-1 implementation on the PM3 uses the old 16 prng. Which then when sim x collects nonces, and it collects the reader nonces, and gives you the option to run mfkey32 tool (which uses the pm3 crypto-1 imp) ... where it only can break old prngs.

Basically, the nonce is generated by a 16-bit linear feedback shift register, same LFSR on both tag and reader. If this LFSR is fixed, then mfkey32 will not work. even if you control one part (tag nonce) the reader nonce is not.

as you might already know, the mfkey32 takes the inputs and tries to reverse the first parts back into a mifare key, then it tries to verify it with taking that key and encrypt next part, where it compares the input part (second nonce) with what it calculated. if it is match it will show the key.

It all falls back to the implementation of the crypto-1.

In my tries, I only get 50% correctness when trying sniffing/mfkey32 on a against a newer tag. I can't see at the moment how it will be different if you try attack the reader or tag it this scenario.

A bad prng is not only showing a "fixed" nonce, the "bad" prng is bad because its randomness is predictable....

iceman1001 avatar Jul 11 '15 14:07 iceman1001

Ok, I think I understand better - but this would logically mean that an old tag (without fixed LFSR) would not be possible to use in systems with new tags, if the LFSR in the reader is also updated. Basically it's a new version of crypto1 deployed, if the protocol changes and becomes backwards incompatible.

Is this true? From what I understand all mifare classic cards are compatible with all mifare classic readers, even though newer cards have protection against the darkside and nested attacks (with a fixed prng), but the readers are not updated, since it would break compatibility.

alfs avatar Jul 11 '15 15:07 alfs

That is a relavant question, the most I gotten out from ppl & hints is that the old LFSR is extended from 16 to 32bits. Leaving old prng still functional. This would explain why I get 50/50 success rate when I try a "fixed" tag with sniffing and mfkey32... Sometimes the LFSR would hit the old prng-deterministic number space and then the tool works..

iceman1001 avatar Jul 12 '15 18:07 iceman1001

@alfs @iceman1001 Gentlmen, do you know if it's possible to send raw commands via android api to get card rndb (32 token rb aka challenge) in response to authenticate command. I tried various things but was unable to.

m17021963 avatar Mar 20 '17 16:03 m17021963

@m17021963 transcieve() is the function you would use, see https://developer.android.com/reference/android/nfc/tech/NfcA.html#transceive(byte[]) but it handles checksumming itself.

Your only option is to modify the Android sources and build a custom version of the android lib, or use an external NFC reader, or a proxmark3 device via USB OTG adapter.

alfs avatar Mar 21 '17 19:03 alfs

@alfs I'm using acr122 but still unable to get card challenge. I'm using direct commands to pn532 but with no luck:

FF 00 00 00 06 D4 42 60 01 7C 6A //IncommunicateThru

Any suggestions

m17021963 avatar Mar 21 '17 23:03 m17021963

Are these cards still available? MCT (with the improvements to talk to these cards of course) and one of these cards sounds like a pretty neat combination but it doesn't look like the cards can be easily sourced?

nvx avatar Apr 30 '19 13:04 nvx

FTR there are currently two implementations I'm aware of:

  • https://github.com/nfc-tools/nfc-supercard
  • https://github.com/RfidResearchGroup/proxmark3 hf mf supercard which is a port of the one above to the Proxmark3 client

doegox avatar Oct 31 '20 22:10 doegox