Emulating NFC tags with the Proxmark

This post's intended audience is those who are familiar with low-level data structures, the basics of NFC and Mifare Classic technologies, and the basic usage of Proxmark hardware.

Proxmark devices are pieces of RFID test equipment commonly used in security research and penetration testing. Each model of device—of which there are several, including some third-party clones—contains antennas suitable for interacting with LF and HF RFID tags; an FPGA used to emulate, communicate, debug, and attack said tags; and an ARM processor used to communicate with a computer over USB, control the FPGA, and perform other functions. Proxmark devices are versatile tools for the RFID or electronic access control enthusiast, but are largely documented with the assumption that the user is abundantly familiar with the underlying RFID and access control technologies.

One feature of the Proxmark is that it can emulate Mifare Classic RFID tags, including the data memory of these tags. This, combined with the ability of Mifare Classic cards to store NFC data, means that one can emulate an NFC tag using a Proxmark.

How to do it

Download mifare-ndef-blank.json. Modify it to your liking by adding NDEF data to empty blocks, starting with block 4. Then, in the Proxmark client, type

 1[usb] pm3 --> hf mf eclr
 2[usb] pm3 --> hf mf eload --1k -f /path/to/mifare-ndef-blank.json
 3[=] Upload 64 blocks 1024 bytes
 4[+] loaded `/path/to/mifare-ndef-blank.json`
 5[=] Uploading to emulator memory
 6[=] ....
 7[?] You are ready to simulate. See `hf mf sim -h`
 8[=] Done!
 9[usb] pm3 --> # Write more stuff to the tag using `hf mf esetblk`.
10[usb] pm3 --> # Remember that indices are 0-based and every 4th block is a special
11[usb] pm3 --> # special sector trailer
12[usb] pm3 --> #hf mf esetblk -b 4 -d 0337D1013355047475636b65722e7468
13[usb] pm3 --> #hf mf esetblk -b 5 -d 652d74776f6d6579732e636f6d2f626c
14[usb] pm3 --> #hf mf esetblk -b 6 -d 6f672f706f7374732f70726f786d6172
15[usb] pm3 --> #hf mf esetblk -b 8 -d 6b2d656d752d6e6663FE000000000000
16[usb] pm3 --> # and/or view the contents of memory
17[usb] pm3 --> #hf mf eview --1k
18[usb] pm3 --> hf mf sim -i
19[=] MIFARE 1K |  UID  n/a
20[=] Options [ numreads: 0, flags: 273 (0x111) ]
21[=] Press pm3 button or send another cmd to abort simulation
22[#] Enforcing Mifare 1K ATQA/SAK
23[#] 4B UID: e68487f3
24[#] ATQA  : 00 04
25[#] SAK   : 08

Then, interact with the emulated tag as desired. Both reading and writing are supported. Once emulation is stopped, one can inspect and dump the emulator's memory using hf mf eview --1k and hf mf esave --1k -f /path/to/dump.json to inspect how the tag data were modified, and one can run hf mf eload --1k -f /path/to/mifare-ndef-blank.json again to reset data on the emulated tag.

The mifare-ndef-blank.json file is an image of a 1K Mifare Classic card formatted to accept NFC data but with no data present. Data must be added to the emulated tag's memory using the TLV (type-length-value) and NDEF (NFC Data Exchange Format) formats. An Adafruit article provides a good overview of NDEF. I also have written a short primer on NDEF and TLV.

Eventually, I will write a Javascript widget that allows one to encode arbitrary data as NDEF and TLV blocks ready to be written to a Mifare Classic card (or the memory of an emulator), but that's out of the scope of this post.

How it works

The stock Proxmark software has an hf mf ndefformat command that formats a Mifare Classic card for NFC usage, but no equivalent that operates on the emulator memory. The mifare-ndef-blank.json file is the rough equivalent of what running hf mf ndefformat does to a card's memory.

To prepare a Mifare Classic card for NFC use, it needs to be formatted to store NDEF records and allow NFC readers to access the card's data blocks1. Doing that requires two things: Mifare Application Directory (MAD) entries must be made to mark all memory blocks as containing NDEF (NFC Data Exchange Format) data, and the keys and permission information of the MAD and NDEF blocks must be set properly.

Two NXP (the manufacturer of the Mifare Classic chip) application notes were helpful when I was setting this up. AN1305 details how to format the card for NFC usage, and AN10787 explains the MAD block.

Setting up the Mifare Application Directory

The Mifare Application Directory (MAD) describes what each sector of the card memory is used for. It is stored on sector 0, blocks 1-2 and starts with an info byte, then a CRC checksum, and then has one sixteen-bit application identifier for each sector. (NDEF data are identified with an application identifier of 0x03 E1.) Bits 0-5 of the info byte point to a sector used to identify the publisher of the card; bits 6-7 are unused. In this application, the info byte is set to 0x00 and each application identifier is set to 0x03 E1. The CRC is computed as shown below and is 0x73. Thus, the MAD sector's contents are as follows:

1-----+-----+-------------------------------------------------+-----------------
2 sec | blk | data                                            | ascii
3-----+-----+-------------------------------------------------+-----------------
4   0 |   0 | E6 84 87 F3 16 88 04 00 46 8E 45 55 4D 70 41 04 | ........F.EUMpA.
5     |   1 | 73 00 03 E1 03 E1 03 E1 03 E1 03 E1 03 E1 03 E1 | s...............
6     |   2 | 03 E1 03 E1 03 E1 03 E1 03 E1 03 E1 03 E1 03 E1 | ................
7     |   3 | A0 A1 A2 A3 A4 A5 FF 07 80 C1 FF FF FF FF FF FF | .........@......

The Sector Trailer (block 3) of Sector 0 contains first Key A (6 bytes), the Access Bits (3 bytes), a General Purpose Byte (which identifies the contents of the sector and is 0xC1 here), and Key B (6 bytes). Key A of Sector 0 must be 0xA0 A1 A3 A3 A4 A5 when the MAD is in use, and Sector 0's Access Bits (here 0xFF 07 80) must be set to allow Key A to read Sector 0. The recommended Access Bits value is 0x78 77 88, but the default of 0xFF 07 80 40 works for our purposes.

CRC computation

Byte 1 (0-based) of Block 1 contains a CRC of the MAD. It is computed by feeding the bytes of the MAD, starting from the last byte of Block 2, to an 8-bit CRC function with polynomial $x^8+x^4+x^3+x^2+1$ and initial value of 0xE3. This can be computed using the Mifare Classic's onboard CRC function or using the Proxmark's reveng command. For the latter case, use reveng -m CRC-8/MIFARE-MAD -c <bytes>. In either case, the info byte is fed in first, the CRC byte is skipped, and the directory bytes are then fed in, starting with the LSB of the first sector byte. If using the reveng command on the Proxmark, this means that the bytes given must be in reverse order to how they would appear in a hex dump.

Setting up the data blocks

Each sector marked for NDEF use in the MAD must have a Key A of 0xD3 F7 D3 F7 D3 F7 and Access Bits that allow Key A to read Sector 0. The recommended Access Bits value is 0x7F 07 88, but the default of 0xFF 07 80 40 works for our purposes. Sector 1 must start with 0x03 00 FE, followed by 0x00 bytes. Further sectors must also contain 0x00.

Thus, the first two sectors will contain

 1-----+-----+-------------------------------------------------+-----------------
 2 sec | blk | data                                            | ascii
 3-----+-----+-------------------------------------------------+-----------------
 4   1 |   4 | 03 00 FE 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
 5     |   5 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
 6     |   6 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
 7     |   7 | D3 F7 D3 F7 D3 F7 FF 07 80 40 FF FF FF FF FF FF | .........@......
 8   2 |   8 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
 9     |   9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
10     |  10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
11     |  11 | D3 F7 D3 F7 D3 F7 FF 07 80 40 FF FF FF FF FF FF | .........@......

1

The Mifare Classic 1K memory is divided into 16 sectors, each with 4 16-byte blocks. The fourth block of each sector contains encryption keys and access information.