NFC Copy Cat is a new security research tool and open hardware device from the Mexican Electronic Cats company. Even when it is already documented in, I want to mention and upload new details, videos, and functionalities relating its last version 1.3 including:

  • Microcontroller SAMD21 ARM 32 bit Cortex M0
  • Memory Flash for support Circuit Python
  • Battery Charger 3.7v
  • Compatible with Adafruit PN532 breakout
  • Compatible with NFC Module V3
  • Compatible with Arduino
  • Compatible with Circuitpython
  • Open Hardware
  • USB Device
  • Bootloader UF2

NFC Copy Cat is a combination of MagSpoof and NFCopy. It implements three buttons and three LEDs. All of them are programable using Arduino IDE.

In the NFC side, the NCC(NFC Copy Cat) device has two different pinouts for SPI connectivity. One connector is for the small PN532 Elechouse board, and the second for Adafruit PN532 board using SPI configuration. Note: Only one card should be connected at the time.

Mentioned that, let me show my configuration to have a better idea of the device. I am using a small PN532 board and a coil behind it for MagSpoof:

The idea behind these two different SPI pinout connectors is to have options for those who want to alternate between the two PN532 board designs depending on the project or on which PN532 the user’ prefers.

To explain the NCC full functionality, I will explain one of its examples: Read_replay_spoof.ino. This script is capable to use all the characteristics on the board, from spoofing mag-stripe data to read, save or emulate NFC transactions using its buttons as triggers and its LEDs as guide.

The code

As normal behavior, the NCC will check connectivity with PN532 when it starts. If something goes wrong detecting the PN532 by SPI, the NCC will not flash its LEDs at all, and it will enter to an infinite cycle: indicating to check the PN532 board SPI configuration:

uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt

The users can comment the while (1); if they decide to use only the MagSpoof part of the code.

The main loop will run three different functions:

void loop(){ // Main loop

The chkdata() will check if the variables tokenString and token contains information that could be used to spoof or emulate a Visa MSD transaction in the execution time. If they have pre-saved data, it will change the assigned LEDs to solid.

void chkdata(){ // Use LEDs to indicate if we have data in "token" or "tokenString" for emulation or MagSpoof
    digitalWrite(L3, HIGH);
    digitalWrite(L3, LOW);
    digitalWrite(L2, HIGH);
    digitalWrite(L2, LOW);

The pre-saved data is a very interesting behavior. Normally, MagSpoof implements a tracks[] constant to save the info and spoof them when the users presses the MagSpoof button. But I added a player to the equation. So, tokenString variable will be used to save a track 2 if it is present in a NFC reading, and LED3 will turn on. If tokenString contains data, its track 2 will be used instead of tracks[] constant values when the user presses the MagSpoof button. So, tokenString could be changed without recompiling the sketch.

Similar behavior applies to NFC button with the token variable. If it contains data, LED2 will be solid. If the variable is empty, and the user presses the NFC button, it will try to read a Visa card. But if token variable has some data, instead of trying to read the card, NCC will try to emulate the card using the Visa MSD protocol. Even this behavior could be applied in the beginning of the sketch; declaring this variable with valid card info:

char token[19] = {0x44,0x12,0x34,0x15,0x01,0x12,0x03,0x12,0xd2,0x41,0x12,0x01,0x10,0x12,0x09,0x99,0x99,0x99,0x1f};

This token variable will activate the emulation process when the NFC button is pressed instead of NFC reading mechanism.

The magbutton() and nfcbutton() are in charge to check if the buttons are pressed. Also they will check if there is pre-saved data in the variables to run a specific process depending on the information.

If the NFC button is pressed and the token variable is empty, the program will run nfcread() function. It will wait and try to list a passive card, specifically a Visa card for this example:

bool nfcread(){ // Wait and try to read a Visa NFC card
  bool success;
  success = nfc.inListPassiveTarget();
  if (success)
  return success;

If a NFC card is in range, it will execute seekTrack2() function. Some characteristics of the function is to initiate the communication with proper APDU commands. In this order: ppse, visa, processing, sfi. When the program select a Visa card using this command:

uint8_t visa[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00}; //13

some cards will respond with a special PDOL(Processing Options Data Object List) answers, which specify the card technology or characteristics that it has; This list has to be used to generate the challenge. The list must follow the exact order and form from the PDOL. For some cards, this is essential to validate a transaction. So, if a PDOL is required which is known by the EMV tag 9F38:

if (apdubuffer[u] == 0x9F && apdubuffer[u+1] == 0x38){

the program will extract it and after that, it will try to generate a correct challenge in format for the next command using the treatPDOL(pdol) function. This function will follow the format, expecting the command in this order:

80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00

After obtaining the PDOL and generating the challenge, this will be send to the card following with the process to obtain track 2; if the track 2 is found and saved for future NFC emulation and MagSpoof, LEDs 2 and 3 will be solid.

To look for track 2 is necessary to find EMV tag 5713 around the SFI answer:

if (apdubuffer[u] == 0x57 && apdubuffer[u+1] == 0x13 && !chktoken){

If track 2 is found in the NFC reading, it will be saved in the token variable as I mentioned before. Also, after the NFC reading process, the program will generate a correct format value using the same track 2 but for MagSpoof using the function formatToken().

Why to use data from NFC to spoof it as magnetic stripe information? This type of attack is called downgrade attack. Occasionally, it is not possible to make a NFC replay attack, but it is possible to make a downgrade attack with mag-stripe data. Yes, even in 2020!

Be Aware

To run this example correctly, you should increase the PN532 buffer in the Adafruit library:

Changing the #define PN532_PACKBUFFSIZ 64 to #define PN532_PACKBUFFSIZ 255 in the Adafruit_PN532.cpp file.

If for some reason it is necessary to upload the bootloader, NFC Copy Cat has some pins for Serial Wire Debug (SWD) connection to reprogram it. This could be implemented by JLink.

Enjoy the tool; be brave enough to share your knowledge & inspire others.