Read & Fuzz contactless smart cards with HydraNFC v2 (Part 2)

In short, this post explains how to initialize an ISO 14443-A smart card with short or standard frame thanks to the hydra NFC v2 console. Straightforwardly, you will be able to send correct commands or  ill-formed command to fuzz a cardIn a next post, we will see how to initialize an ISO 14443-B smart card and how to build TPDUs commands.


ISO 14443

In a previous post, we saw how to connect automatically to a smart card, and then exchange APDUs commands. But, how to initialize a card and what is the communication protocol used to transmit the APDU? In this post, we will focus on the ISO 14443 norm since most of the banking smart cards use it (as well electronic passport). More especially, we will talk about the initialization of an ISO 14443-A card with the Hydra NFC v2 console.

Within this norm, a card can be the A or the B type. Four parts explain it:

  • ISO 14443 Part 1 & 2.
    • It explains how the signal must be modulated. We won’t talk about it in this post.
  • ISO 14443 Part 3.
    • It defines the initialization sequence which is different between type A & B.
    • It explains how a communication frame must be built.
  • ISO 14443 Part 4. It defines the transmission protocol based on the Transport Data Protocol Unit (TPDU) which is common to type A & B:
    • It details initialization commands for instance when the card indicates its communication capacity (communication speed, block size), and the reader can indicate which one to use.
    • How to exchange data thanks to the TPDUs.

ISO 14443-A Initialization sequence

We connect with picocom (but you could use putty as well).

$ picocom -b 115200 /dev/ttyACM0
Type [C-a] [C-h] to see available commands
Terminal ready
> 

This time, we don’t enter in “nfc” menu, but in “dnfc”.

> dnfc
HydraNFC Shield v2 initialized with success.
Device: SPI2
GPIO resistor: floating
Mode: master
Frequency: 10.50mhz (160khz, 320khz, 650khz, 1.31mhz, 2.62mhz, 5.25mhz, 21mhz)
Polarity: 0
Phase: 1
Bit order: MSB first

If we type “help”, we see there is a lot of commands! This menu can be considered as the low-level command sandbox . Don’t worry, we will not use all the commands!

dnfc2> help
Configuration: spi2 [frequency (value hz/khz/mhz)]
Interaction: [cs-on/cs-off] <read/write (value:repeat)> [exit]
   show           Show DNFCv2 parameters
   frequency      Set SPI Bus frequency
   trigger        Setup DNFCv2 SPI2 trigger
   set-nfc-mode   Set NFC Mode and TX/RX BitRate in kbit/s
   get-nfc-mode   Get NFC Mode
   rf-off-on      Set RF field off/on
   reqa           Send ISO 14443-A REQA
   wupa           Send ISO 14443-A WUPA
   send           Send bytes according to the selected mode
   send-auto      Send bytes according to the selected mode and add the two-bytes CRC
   nfc-transp     Enter NFC Transparent Mode
   nfc-stream     Enter NFC Stream Mode
   read           SPI Read byte (repeat with :<num>)
   hd             SPI Read byte (repeat with :<num>) and print hexdump
   write          SPI Write byte (repeat with :<num>)
   <integer>      SPI Write byte (repeat with :<num>)
   <string>       SPI Write string
   cs-on          SPI Alias for "chip-select on"
   cs-off         SPI Alias for "chip-select off"
   [              SPI Alias for "chip-select on"
   ]              SPI Alias for "chip-select off"
   &              Delay 1 usec (repeat with :<num>)
   %              Delay 1 msec (repeat with :<num>)
   ~              SPI Write a random byte (repeat with :<num>)
   A              Toggle AUX[0](PC4) high
   a              Toggle AUX[0](PC4) low
   @              Read AUX[0](PC4)
   exit           Exit DNFCv2 mode

Let see the “set-nfc-mode” command.

dnfc2> help set-nfc-mode
Set NFC Mode and TX/RX BitRate in kbit/s
   nfc-mode       Set NFC Mode
	POLL_NFCA=1, POLL_NFCA_T1T=2, POLL_NFCB=3, POLL_B_PRIME=4, POLL_B_CTS=5, POLL_NFCF=6, POLL_NFCV=7
	POLL_PICOPASS=8, POLL_ACTIVE_P2P=9, LISTEN_NFCA=10, LISTEN_NFCB=11, LISTEN_NFCF=12, LISTEN_ACTIVE_P2P=13
   nfc-mode-tx_br Set TX BitRate
	BR_106=0, BR_212=1, BR_424=2, BR_848=3, BR_52p97=235, BR_26p48=236, BR_1p66=237
   nfc-mode-rx_br Set RX BitRate
	BR_106=0, BR_212=1, BR_424=2, BR_848=3, BR_52p97=235, BR_26p48=236, BR_1p66=237

We select ISO 14443-A type: the reader will send data with the modulation required by the type A. We keep the default bitrate for transmission and reception.

dnfc2> set-nfc-mode nfc-mode 1
nfc-mode = 1
nfc-mode-tx_br = 0
nfc-mode-rx_br = 0
rfalSetMode OK

We deactivate/activate the RF field to restart our card.

dnfc2> rf-off-on

First, the REQA command is sent to detect a card. It is a short frame meaning only 7 coding bits are sent. To ease your understanding, we will not talk about the “protocol bits” in this post, as the start/stop bits and so on. The REQA value is 0x26.

dnfc2> reqa
04 00

Our card is detected since we receive a response: the Answer To Request, named ATQA!

Anti-collision sequence

Once a card was detected, we must execute an anti-collision sequence to select it: the reader asks the card UID, and then send it back to confirm that it wants to talk with it. Another aim of this sequence is to be able to correctly select a specific card when several cards answered the REQA. We will not cover this case, and consider that only one card was detected.

Now, the communication is based on a standard frame, meaning packet of full bytes (ie 8 bits) are sent. Most of the time, a two-byte Cyclic Redundancy Check error code is added at the end of the data to check their integrity. It is specific to the type A, so we named it CRC_A. It is defined in ISO/IEC 13239. Once again, we make a little approximation about the standard frame, it means we do not take about the start/end bit, as well the parity bit. We just talk about coding bit.

First, we send the Select Cascade Level 1 command:

9320
Select Cascade Level 1 commandThe high nibble 2 means we send 2 bytes. The low nibble means we add 0 bits in the command. For instance, if the value was 23, it means we would send 2*8 + 3 = 11 bits.

We use the send command to communicate them to the card. This command sends only the given bytes according to the selected mode.

dnfc2> send 9320
B9 CC 13 71 17 

We received the first 4 UID bytes of the card.

Card UIDBCC. It corresponds to the xor
of the 4 previous bytes.
CRC A
B9 CC 13 7117Hum… Nothing, because we do not
display it for the moment :). We will
add an option to display it or not.

Now, we send back a Select Cascade Level 1 command with the UID to indicate that we want to select this card. This time, we must add a CRC_A in the command. To avoid computing yourself the CRC, you can use the send-auto command that will automatically compute and add the CRC according to the selected mode.

9370B9CC137117CRCA
Select Cascade Level 1 commandThis time we send
7 bytes (without including the
CRC_A)
The card UID + BCCAutomatically
computed

We receive the SAK (Select Acknowledge) indicating the anti-collision sequence is finished.

dnfc2> send-auto 9370B9CC137117
20 
SAKCRC A
20Not displayed

The third bit of the SAK equals 0: it means we received the full card UID. In fact, it size could be 4, 7 or 10 bytes. In this case, we shall have used Select Cascade Level 2 or 3 commands.

Request for answer to select (RATS)

Ok, so the reader and the card agreed to talk together. Now, the reader can inform the card about its communication preferences with the RATS command. It enables to indicate to the card:

  • the Frame Size for proximity coupling Device Integer (FSDI) (high nibble). This integer indicates the maximum frame size that we’ll be sent by the reader (Frame Size for proximity coupling Device or FSD). It is typically the thing you would like to set to its lowest value, and then send a frame with a bigger value 🙂 .
FDSI012345678Other
FSD (in bytes)16243240486496128256RFU
  • the CID. It enables to indicate the channel number. We set it to 0.
Start byteParameterCRC A
E000 (High nibble: FSDI, low nibble CID) Automatically
computed

We send the command.

dnfc2> send-auto E000 
0A 78 80 82 02 20 63 CB A3 A0

The card answers with the Answer to select (ATS) its communication options: its frame size, the presence of specific bytes, communication speed…

0ALength of the full command (this byte included) without the CRC_A
787: Bytes TA1/TB1/TC1 transmitted
8: FSCI. It is like the FDSI but for the card. So, it tells the reader that it can send up to 256 bytes.
80TA1. It indicates the card supported communication speed.
82TB1. It deals with delay between the frames.
02TC1. It indicates if optional byte will be present in the TPDU header.
20 63 CB A3 A0Historical bytes. It can gives other information about the card.
CRC_ANot displayed

Protocol and parameter selection request (PPS)

Finally, the reader can send a PPS to customize the communication speed. We send here a default value where no modification is done (and the speed modification is not implemented in this command).

dnfc2> send-auto D001          
D0 

The card acknowledges our parameters. And now, we are ready to send TPDUs!

In fact, all the initialization sequence was done automatically done with the connect command that we saw in the previous post. Do you remember?

> nfc
NFCv2> connect
> 26
< 04 00 
> 93 20 
< B9 CC 13 71 17 
> 93 70 B9 CC 13 71 17 
< 20 
> E0 00 
< 0A 78 80 82 02 20 63 CB A3 A0 
> D0 01 
< D0 
ISO 14443-A card detected.

Another fun fact, the ISO 14443-A norm is used for the electronic passport. If you try to connect twice to your passport for instance with the connect command in the nfc menu, you will see the UID is not the same:

NFCv2> connect
> 26
< 04 00 
> 93 20 
< 08 99 8B 85 9F 
[Line removed...]
NFCv2> connect
> 26
< 04 00 
> 93 20 
< 08 46 13 2C 71 
[Line removed...]
NFCv2> 

It is weird. First time, the card UID is 99 8B 85 9F, and the second time it is 46 13 2C 71. A card UID is supposed be static, no? Yes, but for anonymity reason, and to prevent tracing someone with its ePassport UID, it is mandatory that the returned value is random.

What next?

We saw that we can perform the initialization sequence of an ISO 14443-A card within the Hydra NFC v2 menu:

  • We can send short frame like the REQA.
  • We can send raw standard frame, with or without the automatic computation of the CRC_A. So, you can send correct frame, or random data to fuzz the card.

In a next post, we will send:

  • How to initialize an ISO 14443-B smartcards.
  • How to build TPDUs.
  • And how to script all these commands with Python.

Read & Fuzz contactless smart cards with HydraNFC v2 (Part 1)

In short, this post explains how to exchange APDU commands straightforwardly with contactless smartcards thanks to the Hydra NFC v2, either with a serial console or a python driver. As you control any bytes sent to the card, you can send ill-formed command to fuzz a card at the APDU level. In a next post, we will see how to send commands at a lower level with TPDUs commands or ISO 14433 initialization commands. Fuzzing at this level would be far more efficient.


APDU: the basic communication structure

How works a communication between a reader and a smartcard?

  • The reader initializes the communication. The RF field is activated, and several low level commands are exchanged to detect a compatible card.
  • Then, the reader exchange information with the card using the APDU (Application Protocol Data Unit) protocol. It sends a command to the card, which then answer back with a response.

What is the structure of an APDU? Hereafter, you have the generic format of a command.

CLAClass byte
INSInstruction byte. It characterizes the type of command.
P1Parameter byte 1. It is an option related to the INS field.
P2Parameter byte 2. It is an option related to the INS field.
LcLength of the Data field
DataData Byte
LeNumber of bytes expected in the card response

And below, you have the generic format of a response.

DataCard response (optional)
Status Word2 bytes named SW1 & SW2

We know the format of the APDUs. But which information is exchanged?

  • Several applications can be embedded by the card, so the reader must select the one to use.
  • Then, you can have command enabling to read information about the card.
  • Finally, some of them enable to make payment:
    • The terminal wants to make a payment. It sends a command indicating among other things the amount, the date, the currency.
    • The card checks if the information is correct, for instance if the amount is not too high. If it is accepted, its response will contain a cryptogram to prove the transaction was certified.
    • The terminal extracts this cryptogram, and check it to validate the transaction.

Sending APDU with the Hydra NFC v2

The goal of this post is not to explain all the commands of a transaction, but just to show you can send APDUs sraighforwardly with the Hydra NFC.

We saw that the reader needs to select the card payment application:

  • But it does know which application is embedded: Mastercard, Visa …
  • So, he selects a special application available on all the smart cards. Its response will list all the installed applications. Its name is 2PAY.SYS.DDF01.
  • The APDU command to send is described below:
CLA00
INSA4 (Select command)
P100
P204 (The application name is set in the Data field)
Lc0x0E
Data32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 (the application name in hexadecimal)
Le0x00

Let use the Hydra NFC v2!

We connect with picocom (but you could use putty as well).

$ picocom -b 115200 /dev/ttyACM0
Type [C-a] [C-h] to see available commands
Terminal ready
> 

We type “help” to list the available commands.

> help
Available commands
   help           Available commands
   history        Command history
   clear          Clear screen
   show           Show information
   logging        Turn logging on or off
   sd             SD card management
   nfc            NFCv2 mode
   dnfc           Debug/Developer NFCv2 mode
   debug          Debug mode
> 

We select the nfc menu, and type once again help to get information.

> nfc 
NFCv2> help
NFCv2 mode
   sd             SD card management
   show           Show NFC parameters
   nfc-all        Select technology NFC-A/B/V/F
   nfc-a          Select technology NFC-A (ISO14443A includes MIFARE...)
   nfc-b          Select technology NFC-B (ISO14443B)
   nfc-st25tb     Select technology NFC-B (ISO14443B ST25TB)
   nfc-v          Select technology NFC-V Vicinity (ISO/IEC 15693)
   nfc-f          Select technology NFC-F Felica
   scan           Scan selected technology (NFC-A/B/V/F...)
   emul-3a        Emul Tag ISO14443A
   ce             Set Tag properties for Card Emulation (UID, SAK, T4T params...)
   emul-t4t       Emulate Type 4 Tag with preset Tag properties
   connect        Connect to a smartcard (ISO 14443 A & B)
   connect-opt    Set options for connect & send commands
   send           Send APDU data to a card initialized with the connect command (only ISO 14443 A & B tags)
   exit           Exit NFC mode

We use the connect command to detect and initializes smart card.

NFCv2> connect
> 26
< 04 00 
> 93 20 
< B9 CC 13 71 17 
> 93 70 B9 CC 13 71 17 
< 20 
> E0 00 
< 0A 78 80 82 02 20 63 CB A3 A0 
> D0 01 
< D0 
ISO 14443-A card detected.

An ISO 14443-A card was discovered, and some information were exchanged. We will talk about it later.

Know, we can send the APDU command with “send”.

NFCv2> send 00A404000E325041592E5359532E444446303100                     
> 1A 00 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 
< AA 00 
> 0B 00 46 30 31 00 
< 1B 00 6F 57 84 0E 32 50 41 59 2E 53 59 53 
> BA 00 
< 1A 00 2E 44 44 46 30 31 A5 45 BF 0C 42 61 
> BB 00 
< 1B 00 1B 4F 07 A0 00 00 00 42 10 10 50 02 
> BA 00 
< 1A 00 43 42 87 01 01 9F 28 08 40 02 00 00 
> BB 00 
< 1B 00 00 00 00 00 61 23 4F 07 A0 00 00 00 
> BA 00 
< 1A 00 04 10 10 50 0A 4D 41 53 54 45 52 43 
> BB 00 
< 1B 00 41 52 44 87 01 02 9F 28 08 40 00 20 
> BA 00 
< 0A 00 00 00 00 00 00 90 00 
6F 57 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 45 
BF 0C 42 61 1B 4F 07 A0 00 00 00 42 10 10 50 02 43 42 87 01
01 9F 28 08 40 02 00 00 00 00 00 00 61 23 4F 07 A0 00 00 00
04 10 10 50 0A 4D 41 53 54 45 52 43 41 52 44 87 01 02 9F 28 
08 40 00 20 00 00 00 00 00 90 00 

The APDU response is: 6F 57 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 45 BF 0C 42 61 1B 4F 07 A0 00 00 00 42 10 10 50 02 43 42 87 01 01 9F 28 08 40 02 00 00 00 00 00 00 61 23 4F 07 A0 00 00 00 04 10 10 50 0A 4D 41 53 54 45 52 43 41 52 44 87 01 02 9F 28 08 40 00 20 00 00 00 00 00 90 00.

We can interpret the data with emvlab.org/tlvutils. We will see later the meaning of the command line starting with a “>” or a “<“.

OK, but what happens if you want to send a lot of commands? And parse their results to create the next commands? It will be very tedious to forge/analyze them one by one…

No problems, there is a python driver to do it!

Hydra NFC v2 python driver

There is another way to communicate with a python driver https://github.com/gvinet/pynfcreader:

  • It does not simply create a serial communication and send the commands that we saw previously.
  • In fact, it uses a dedicated mode of the HydraNFC v2 named BBIO. In short, it enables to send short binary commands, instead of huge ASCII text.

Let see a script to communicate with our card:

import time
from pynfcreader.devices.hydra_nfc_v2 import HydraNFCv2
from pynfcreader.sessions.iso14443.iso14443a import Iso14443ASession

hydra_nfc = HydraNFCv2(port="/dev/ttyACM1", debug=False)
hn = Iso14443ASession(drv=hydra_nfc, block_size=250)

hn.connect()
hn.field_off()
time.sleep(0.1)
hn.field_on()
hn.polling()

With this driver:

  • you can scripts your commands,
  • and you can use it easily with a lot of python library enabling to communicate with contactless smart card.

What next?

So with the Hydra NFC v2:

  • You have a contactless smart card reader available either with a serial console or a Python library.
  • You can send incorrect APDU commands to fuzz the smartcards.

But, there still other fun things to do:

  • The APDUs are not directly exchanged between the reader and the card. They are encapsulated in Transport Protocol Data Unit (TPDU) frames. It could be fun to able to send.
  • In the same way, specific commands are sent to detect and intialize the card.

In the previous outputs, these commands correspond to the line starting with a “>” or a “<“, for instance:

  • A REQA: “> 26”
  • A TDPU: “> 1A 00 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44”

The TPDU and the initialisation sequence is described by the ISO 14443 norm. In a next post, we will explain this communication protocol, and see how it’s easy to play with it thanks to the Hydra NFC v2!