ikarus23 / MifareClassicTool

An Android NFC app for reading, writing, analyzing, etc. MIFARE Classic RFID tags.
http://www.icaria.de/mct/
GNU General Public License v3.0
4.68k stars 903 forks source link

App reads data but does not know the reading key [Fudan knock-off cards] #377

Closed vykintazo closed 1 year ago

vykintazo commented 2 years ago

Sorry if this is not appropriate place to ask as my question might be more Mifare than app related. But still here's my question: with the app I read the card and one sector seemingly lacks Key A, but is still fully read. Looking at the Access Conditions, it looks like all the blocks require Key A for all operations. And still I can see the full data of the sector:

B99ED9234E73EC260616D2061F1AD086
A7C41CC5DFC701D6DD7A2C3303000000
D7FF1EFEDAF924F8D8C71EC6DAC11487
------------FF078069FFFFFFFFFFFF

Does that mean that the data above is incorrect/gibberish, or that it actually read the key but cannot show it? Or did I misunderstand how authentication works?

webmagic86 commented 2 years ago

Up for you, as I have a similar situation reading a mifare tag, sector 1 reads as follows:

0000D2000000088E0000000000000000
00000000000000000000000000000000
A0B1C2D3E4F5FFFFFFFFFFFFFFFFFFFF
------------FF0F00FFFFFFFFFFFFFF

I was able to copy this sector to a magic tag (gen2) but last sector is not identical, "-" were replaced by "F", and also access conditions were changed in the copy. As a consequence, reader simply discards the cloned tag.

0000D2000000088E0000000000000000
00000000000000000000000000000000
A0B1C2D3E4F5FFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFF078069FFFFFFFFFFFF
ikarus23 commented 2 years ago

Hi This seems like a bug. The access conditions state that reading the tag is only possible with key A. Since the data of the tag have been read the key A must be known. In your case, @vykintazo, I'm pretty sure it is the default key FFFFFFFFFFFF because the access conditions are the default access conditions.

Now for the real interesting part: I have no idea why! This looks like a super common case and I never have seen this before. Most of the time, this is due to some device or version specific stuff.

@webmagic86 It seems that your read problem is the same. However, the write result is expected. MCT can not guess data (--=unknown data) and a MIFARE Classic card can only be written block by block. So if there are unknown data in a block, MCT will skip the block.

vykintazo commented 2 years ago

@ikarus23 thanks for the reply! Recently, I actually tried to clone my card as @webmagic86 did, and it did copy everything but used the default FF key for the unknown one. And it didn't work, however I cannot confirm that it didn't precisely because of this issue. The said card uses default key for some sectors, and a (known) custom one for others - it would be weird that the single missing one would be different from others, so I'll try manually setting it to the other than the default one when I can. Perhaps it's also worth noting that it seems like other reader apps, like the one from NXP, also return exact same results. That could possibly mean some issues on the OS level I suppose. And indeed I am using Samsung Galaxy S20 with Android 12 - I've seen people having various issues with this Android version and this one might one of them.

webmagic86 commented 2 years ago

@ikarus23 I did several tests, using Android 9 (Sony XZ1) and 11 (Pixel 4a), all reporting the same readings. @vykintazo my card has default keys for sector 0 (copied on the magic tag just fine, including UID), sector 1 is strange as mentioned, while the other sectors are just blank with defaults.

Now I am just wondering why the copied tag is discarded.. does the reader try to read with another key? A-key is replaced by FFFFFFFFFFFF after the copy, but if the key was wrong, why was MCT able to read the previous blocks? (I mean sector 1, blocks 0-1-2)

Anyway, I am waiting for a PN532+USB-TTL to do further research and find out what is the real A-key, if it's not the default, I will go through nested attack and so on. I will update you!

ikarus23 commented 2 years ago

Thanks for the feedback. @webmagic86 I'm really interested in your test results with the PN532. Maybe this will help in understanding why MCT can read the data (blocks 0-2) without key A.

As for why the reader discards the copied tag: There are readers out there with "clone detection". Sometimes the cloned the clone is not perfect. E.g. values like the SAK might not be the same.

Also, your block 0 0000D2000000088E0000000000000000 looks very off. The UID does not look very valid. Does the tag have a 4 bytes long UID? If so, the BCC in block 0 is not correct. If it is a 7 bytes long UID, make sure your UID changeable tag is designed for 7-byte-UIDs.

@vykintazo Interesting that other apps show the same behavior. Still though I would be important that you can be really sure that you know key A. Do you have access to another device to check if it will behave differently with the same tag? Or maybe an USB RFID/NFC reader?

webmagic86 commented 2 years ago

Also, your block 0 0000D2000000088E0000000000000000 looks very off. The UID does not look very valid. Does the tag have a 4 bytes long UID? If so, the BCC in block 0 is not correct. If it is a 7 bytes long UID, make sure your UID changeable tag is designed for 7-byte-UIDs.

That was sector 1, block 0, it probably contains application data read/wrote by the reader. Just to be clear, my first two sectors are:

+Sector: 0
DE30DE0D3D0804006263646566676869
00000000000000000000000000000000
00000000000000000000000000000000
FFFFFFFFFFFFFF078069FFFFFFFFFFFF
+Sector: 1
0000D2000000088E0000000000000000
00000000000000000000000000000000
A0B1C2D3E4F5FFFFFFFFFFFFFFFFFFFF
------------FF0F00FFFFFFFFFFFFFF

As I said before, sector 0 was copied without problems with a magic tag. I hope my PN532 kit will arrive tomorrow. ;)

webmagic86 commented 2 years ago

First tests with PN532+USB-TTL, but still no luck trying to recover my A-key on sector 1.

mfoc ERROR: No success, maybe you should increase the probes. <- infinite loop if I increase the probe number mfcuk diff Nt always 1, while auths is increasing <- running on sector 1 using the known key from sector 0 (FFFFFFFFFFFF), but no progress during last night, stopped milazycracker when starting, it uses mfoc, but it's not working

I came across a site that says the card might have a 'static nonce', so all the traditional methods won't work. Proxmark3 probably will solve the issue, but I am not 100% sure. Still haven't found an explanation on how MCT reads the protected blocks. Any help? @ikarus23 @vykintazo

ikarus23 commented 2 years ago

Hi @webmagic86, thanks for clearing up that the sector in question is sector 1 not 0.

There could be serval reasons why you are not be able to crack the key:

  1. The card might have the improved PRNG. This makes the card no longer vulnerable to the "nested attack". Luckily you can use the "hardnested attack" to get the key. Have a look at https://github.com/nfc-tools/mfoc-hardnested (For the nested attack you always have to know at least one key. Should be no issue in your case.)
  2. The card might have a static nonce. This is not normal and not complying with the MIFARE Classic specification. However, it is very common for cheap Chinese MIFARE Classic cards (not original by NXP). You can still get the key, but I don't know if mfoc or mfcuk are up to the task. The Proxmark3 can do it (I tired it my self), but it will be another $50 bucks. If you want to get more into RFID hacking I strongly recommend the Proxmark3. No better tool around.
  3. The tag is a unknown and unofficial MIFARE Classic tag. There are lots of them out there. Sometimes they do not comply with the specification (e.g. static noce). If this is the case I don't think I can do anything for you. Sorry.
webmagic86 commented 2 years ago

Hello @ikarus23, I think I made a big step forward in understanding the issue. Using the app I managed to write and update sector 1, block 0 on the original tag. Funnily enough, I used FFFFFFFFFFFF as a key, and the block was updated! Reader also detected the new values, so I understood also the logic behind the values.

At this point, key is correct, write has been performed, while the app for some reasons keeps showing ------------ in the trailer, even after the successful write I did.

3. The tag is a unknown and unofficial MIFARE Classic tag. There are lots of them out there. Sometimes they do not comply with the specification (e.g. static noce). If this is the case I don't think I can do anything for you. Sorry.

I think so, this is the correct answer. I tried NXP TagInfo and it shows: Unknown Mifare class IC, possibly cloned.

I was lucky enough to go further in this case, if you want me to do other tests, don't hesitate to ask. I still need to understand how to have a proper clone, but for now modifying is enough. ;)

webmagic86 commented 2 years ago

This morning I understood why I was able to write sector 1, block 0. Access conditions (FF0F00 + FF as user bytes) allowed me to update the block using key B, which was default as well. FFFFFFFFFFFF

Luck was on my side ;) so @ikarus23 your app is correct, we still don't know key A!

ikarus23 commented 2 years ago

Just a reminder for me when I will have time looking into this more: As discussed with @webmagic86 on the RFID Hacking Discord, MCT must have changed the block using key A, because key B can not be used for writing (due to the ACs). Therefore, MCT must know that the default key A is the correct one. But then, why does it not display this key in the dump editor?...

ikarus23 commented 1 year ago

Hi @webmagic86! Long time since I had a look into this, but today a had a bit of spare time and tried to reproduce it. I configured a card like you described in https://github.com/ikarus23/MifareClassicTool/issues/377#issuecomment-1084926486. However, I can not reproduce it. My tag reads/writes fine (so does yours) but key A for sector 1 is displayed for me correctly.

At this point, I'm not sure if there is an issue with your tag. Could be. One explanation I have is that the tag sometimes returns negative to an authentication command, although the key was correct. I saw that happen on some devices. There is an option for this strange behavior. You can try the "retry the authentication" option and set it to something like 5.

Also very important: Have you tried other apps like NXP's TagInfo? Since you use the default keys, this app should also be able to read your tag. Would be interesting how they react.

webmagic86 commented 1 year ago

At this point, I'm not sure if there is an issue with your tag. Could be. One explanation I have is that the tag sometimes returns negative to an authentication command, although the key was correct. I saw that happen on some devices. There is an option for this strange behavior. You can try the "retry the authentication" option and set it to something like 5.

No change after setting up the authentication to 5. MCT still filling keyA with ------------ (version 4.0.5)

Also very important: Have you tried other apps like NXP's TagInfo? Since you use the default keys, this app should also be able to read your tag. Would be interesting how they react.

TagInfo

No doubt tag is a cheap chinese clone.. got several with different UID and with the same problem.

webmagic86 commented 1 year ago

Update: I finally got my hands on PM3 and tested the card.. got my real keyA 001122334455 (maybe we can add it in the dictionary).

+Sector: 0
DE30DE0D3D0804006263646566676869
00000000000000000000000000000000
00000000000000000000000000000000
FFFFFFFFFFFFFF078069FFFFFFFFFFFF
+Sector: 1
0000D2000000088E0000000000000000
00000000000000000000000000000000
A0B1C2D3E4F5FFFFFFFFFFFFFFFFFFFF
001122334455FF0F00FFFFFFFFFFFFFF

Reading the json dump file and the access conditions of sector 1 (it seems a different interpretation):

"1": {
      "KeyA": "001122334455",
      "KeyB": "FFFFFFFFFFFF",
      "AccessConditions": "FF0F00FF",
      "AccessConditionsText": {
        "block4": "read AB; write AB; increment AB; decrement transfer restore AB", <-- BLOCK WITH DATA
        "block5": "read AB; write AB; increment AB; decrement transfer restore AB", <-- EMPTY
        "block6": "read AB; write AB; increment AB; decrement transfer restore AB", <-- OTHER DATA
        "block7": "read A by A; read ACCESS by A; read/write B by A",
        "UserData": "FF"
      }
    }

It says write AB, so it explains why I was able to update it using keyB FFFFFFFFFFFF. What do you think? @ikarus23

ikarus23 commented 1 year ago

Wow! What a find. Actually 2 finds!

I will look into the bug and add the key. Thank you so much for going through with this!

ikarus23 commented 1 year ago

Hmm. After looking at the code, I can not see an error so far. The Access Condition decoder of MCT seem to be correct. Compared to the Proxmark3 decoder, it just does an extra step: If key B is readable it can not be used for reading/writing blocks. MCT takes that into account.

You can see/verify this here: http://calc.gmss.ru/Mifare1k/ Your configuration FF0F00 is just C1, C2 & C3 set to 0 for all blocks and the sector trailer. The Proxmark3 decoder just takes the values of the table but MCT just displays A because the B in A|B can not be used. The footnote says so:

if Key B may be read in the corresponding Sector Trailer it cannot serve for authentication (all grey marked lines in last table). As a consequences, if the reader authenticates any block of a sector which uses the grey marked access conditions and using key B, the card will refuse any subsequent memory access after authentication.

So far I have only one explanation: The fake MIFARE Classic IC allows to use key B although it should not be possible. There is no doubt it is not an original Tag because of the manufacturer data being 6263646566676869. This is typical for tags from Fudan, a Chinese manufacturer of cheap cloned MIFARE Classic ICs.

I have some tags like this at home. I will try to verify this, as soon as I'm home again.

webmagic86 commented 1 year ago

Yes @ikarus23, I remember we discussed about it, and I agree with the explanation you gave. Fudan may have left this vulnerability on purpose. Let's see if you can reproduce the bug. ;)

ikarus23 commented 1 year ago

Not finished with all the testing but here is what I have so far:

  1. I was able to reproduce the issue with a Fudan card. Key B is readable but still can be used for authentication and writing.
  2. I tried to reproduce it on an old official tag (at least I hope it is official). When key B is readable i got: authentication with key B works (expected), the write command went through (unexpected), the data was NOT written (expected). I have to do more testing here. However, this has nothing to do with this issue.
  3. I configured the old official tag to the access conditions FF0F00. Everything works as expected. MCT can not read the sector if key A is not known, since key B is readable and can not be used for reading/writing.
  4. The observations from 3. made me now realize: You should have never been able to read sector 1 as you have in https://github.com/ikarus23/MifareClassicTool/issues/377#issuecomment-1084926486. If key B is readable it can not be used for reading. And as the dump correctly stated: you don't know key A. This means: the cheap clone cards allow users to use key B for reading/writing, even if it is readable...

Not sure How to go from here. I hate to implement more things just for cards that violate the specs. I will have to think about it. Regardless, now we know how your situation was possible. Just because of a cheap card that does not follow the specs.

ikarus23 commented 1 year ago

With regards to this issue: I think I will change nothing for now. The information provided by MCTs access condition decoder is correct. These tags just violate the specification. And even in that case, MCT tries to make the best of it. You can read/write them, even if the ACs don't allow it. That should be good for now.

Thanks again for all the information!