Investigating Blue 125khz RFID tags (from China) bought off Amazon with a Proxmark3

My Proxmark3 RDV40.1 finally arrived yesterday and I have been busy investigating this RFID reader/writer/copier bought off Amazon.  It came bundled with soem blue plastic RFID tags (125khz and 13.56Mhz) and some 125khz RFID cards.  Before the Proxmark3 came I played around with reading and writing some of the included cards but had no way to really verify anything.

Finally I got a hold of a Proxmark3 and it took the better part of yesterday to get it up and going.  This was mostly getting the built from source software working then programming the firmware to the Proxmark3 hardware.

Searching for hours on end about these mysterious tags that I could program with the Chinese copier, read with the Proxmark3, but not program with the Proxmark3 was quite frustrating.  One thing to mention about the strategy here, this works IF you have own or have access to the programmer that programmed the tags.

From internet searching (picture searches are useful) for these blue tags I ran across some possible candidates for them.  I found mentions of TK4100, EM4100, EM4305, T5577 and EM4305

While looking around these two posts provided a wealth of information of where to get started in figuring out the password how how to program the blue tags.
http://www.proxmark.org/forum/viewtopic.php?id=6388
http://www.proxmark.org/forum/viewtopic.php?id=6245

I few lessons learned, these blue 125khz tags do not have the best of antennas in them, even if they can be read, writing data is a whole different story.  These tags are powered from the magnetic field generated by the reader/writer and if not enough power can be drawn from the electromagnetic field the writes will fail.  They need to be positioned in the “sweet spot” of the Proxmark3 to be written to correctly, or attach an antenna with higher gain.

This is the proxmark3 client source that I am using, commands will be slightly different with a different version.

https://github.com/RfidResearchGroup/proxmark3

After some investigation it is not uncommon for these copiers from China to put passwords on the tags they copy.  Once the tag has a password it can not be reprogrammed without that password.  Good thing for us that this data is not encrypted and we can just sniff it with the Proxmark3 and read off the password.

The Proxmark3 client has a brute force script that tries common passwords, but lets go through the sniffing method.

First we are going to read the tag and see what additional data is returned.

Startup the Proxmark3 software, this is the version output from what I am using for reference.

[=] Session log /Users/user/.proxmark3/logs/log_20210219.txt
[+] loaded from JSON file /Users/user/.proxmark3/preferences.json
[=] Using UART port /dev/tty.usbmodemiceman1
[=] Communicating with PM3 over USB-CDC


  ██████╗ ███╗   ███╗█████╗ 
  ██╔══██╗████╗ ████║╚═══██╗
  ██████╔╝██╔████╔██║ ████╔╝
  ██╔═══╝ ██║╚██╔╝██║ ╚══██╗
  ██║     ██║ ╚═╝ ██║█████╔╝       Iceman ☕
  ╚═╝     ╚═╝     ╚═╝╚════╝    ❄️ bleeding edge

  https://github.com/rfidresearchgroup/proxmark3/


 [ Proxmark3 RFID instrument ]

 [ CLIENT ]
  client: RRG/Iceman/master/v4.9237-3016-gf6bca6e3a 2021-02-06 18:19:42
  compiled with Clang/LLVM Apple LLVM 12.0.0 (clang-1200.0.32.28) OS:OSX ARCH:x86_64

 [ PROXMARK3 ]
  firmware.................. PM3RDV4
  external flash............ present
  smartcard reader.......... present
  FPC USART for BT add-on... absent

 [ ARM ]
  bootrom: RRG/Iceman/master/release (git) 
       os: RRG/Iceman/master/v4.9237-3016-gf6bca6e3a 2021-02-06 18:20:33
  compiled with GCC 10.2.1 20201103 (release)

 [ FPGA ] 
  LF image built for 2s30vq100 on 2020-07-08 at 23: 8: 7
  HF image built for 2s30vq100 on 2020-07-08 at 23: 8:19
  HF FeliCa image built for 2s30vq100 on 2020-07-08 at 23: 8:30

 [ Hardware ]
  --= uC: AT91SAM7S512 Rev A
  --= Embedded Processor: ARM7TDMI
  --= Nonvolatile Program Memory Size: 512K bytes, Used: 310789 bytes (59%) Free: 213499 bytes (41%)
  --= Second Nonvolatile Program Memory Size: None
  --= Internal SRAM Size: 64K bytes
  --= Architecture Identifier: AT91SAM7Sxx Series
  --= Nonvolatile Program Memory Type: Embedded Flash Memory

I previously copied an HID 125khz card using the copier from China, and now I am going to read that card and attempt to erase/write it.  First of all here is the output from the LF search.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> 

We notice it detected a T55xx chip, which gives us a hint of what kind of chip is in this card, so lets try to dump the card.

[usb] pm3 --> lf t55xx dump
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 80000000 | .0000000000000000000000000000000 | ....
[+]  01 | 80000000 | .0000000000000000000000000000000 | ....
[+]  02 | 80000000 | .0000000000000000000000000000000 | ....
[+]  03 | 80000000 | .0000000000000000000000000000000 | ....
[+]  04 | 80000000 | .0000000000000000000000000000000 | ....
[+]  05 | 80000000 | .0000000000000000000000000000000 | ....
[+]  06 | 80000000 | .0000000000000000000000000000000 | ....
[+]  07 | 80000000 | .0000000000000000000000000000000 | ....
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 80000000 | .0000000000000000000000000000000 | ....
[+]  01 | 80000000 | .0000000000000000000000000000000 | ....
[+]  02 | 80000000 | .0000000000000000000000000000000 | ....
[+]  03 | 80000000 | .0000000000000000000000000000000 | ....
[+] saved to json file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.json
[+] saved 12 blocks to text file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.bin
[usb] pm3 --> 

We aren’t getting any data from the chip but retrying the LF search command we know there is data on it.  We won’t be able to dump the chip if there is a password on it.  Let’s try to figure out what password the reader put on the tag.  To do this we can capture the data being sent from the Chinese copier.  Here is how to set it up and do the capture.

[usb] pm3 --> lf config --trig 64 --dec 2 --bps 64

[#] LF Sampling config
[#]   [q] divisor.............95 ( 125.00 kHz )
[#]   [b] bits per sample.....8
[#]   [d] decimation..........2
[#]   [a] averaging...........No
[#]   [t] trigger threshold...64
[#]   [s] samples to skip.....0 
[#] LF Sampling Stack
[#]   Max stack usage.........4232 / 8480 bytes
[usb] pm3 --> lf snif

This will setup the Proxmark3 to capture the data coming from the Chinese copier. Read the chip that we want to unlock using the Chinese copier and then “write” it into the Proxmark3 (as of the Proxmark3 is a chip). The Proxmark3 should capture the write attempt and return the prompt, then execute the following two commands and a waveform should appear, we are going to decipher this waveform bit by bit.

[usb] pm3 --> data samples
[usb] pm3 --> data plot

Proxmark3 T55xx password waveform

This is the password that the Chinese copier is trying to set, all we have to do is decipher the bits.  Apply a filter on the waveform above as shown below to help with visualization.

Proxmark3 T55xx password waveform

Our waveform should have some red lines over it which make it easier to read now.

Proxmark3 T55xx password waveform

Now we just read off the bits off according to the protocol (which I don’t have handy at the moment).

Proxmark3 T55xx password waveform

Here is a decode of the bits.

bits byte description
1100 password OP code
0001 1001 0x19 password byte
1001 0010 0x92 password byte
0000 0100 0x04 password byte
0010 0111 0x27 password byte
111 trailing bits

Our password is therefore 0x19920427.  Lets try again to dump the chip with the correct password. First run lf search so the Proxmark3 sets configures for the card, we can also manually configure with lf t55xx config if we know the parameters.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55 detect -p19920427
[=]      Chip Type      : T55x7
[=]      Modulation     : FSK2a
[=]      Bit Rate       : 4 - RF/50
[=]      Inverted       : Yes
[=]      Offset         : 33
[=]      Seq. Term.     : No
[=]      Block0         : 0x00107070 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : Yes
[=]      Password       : 19920427

We see the chip, and the password is correct as it responds.  We found a T55x7 chip (actually a T5577 chip in in this tag). The chip is in an emulation mode for HID 125khz now so its modulation and such has been changed to match the chip it copied.  Let’s attempt to dump its data.

[usb] pm3 --> lf t55xx dump p 19920427
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.

We are getting a safety check to make sure we know what we are doing. Attempting to use a password on a card that does not have one set can damage it hence the warning. We know the password is correct and we can dump the card (at your own risk) since we are going to override this warning.

[usb] pm3 --> lf t55xx dump p 19920427 o
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[=] Safety check overridden - proceeding despite risk
[+]  00 | 00107070 | 00000000000100000111000001110000 | ..pp
[+]  01 | EAAACAAA | 11101010101010101100101010101010 | ....
[+]  02 | AB4D4D2B | 10101011010011010100110100101011 | .MM+
[+]  03 | 55332D28 | 01010101001100110010110100101000 | U3-(
[+]  04 | 00000000 | 00000000000000000000000000000000 | ....
[+]  05 | 00000000 | 00000000000000000000000000000000 | ....
[+]  06 | 00000000 | 00000000000000000000000000000000 | ....
[+]  07 | 19920427 | 00011001100100100000010000100111 | ...'
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 00107070 | 00000000000100000111000001110000 | ..pp
[+]  01 | E01500D0 | 11100000000101010000000011010000 | ....
[+]  02 | 3075F62B | 00110000011101011111011000101011 | 0u.+
[+]  03 | 00A00003 | 00000000101000000000000000000011 | ....
[+] saved to json file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.json
[+] saved 12 blocks to text file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.bin

Here is our dump. Next let’s try to erase the card (to clear the password also). There are password set/clear commands, but if you just want to recover card so it can be used on another reader it is easy to just wipe it.

Lets first search for the card, then attempt to erase it, then try to search for it again. If we erased it it should not return any data.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx wipe
[=] Target T55x7 tag
[=] Default configuration block 000880E0

[=] Begin wiping...
[=] Writing page 0  block: 00  data: 0x000880E0 
[=] Writing page 0  block: 01  data: 0x00000000 
[=] Writing page 0  block: 02  data: 0x00000000 
[=] Writing page 0  block: 03  data: 0x00000000 
[=] Writing page 0  block: 04  data: 0x00000000 
[=] Writing page 0  block: 05  data: 0x00000000 
[=] Writing page 0  block: 06  data: 0x00000000 
[=] Writing page 0  block: 07  data: 0x00000000 
[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands

It appears the wipe command didn’t work, this is because there is a password set, we need the password to change data on the card, let’s try again with the password.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx wipe -p 19920427
[=] Target T55x7 tag
[=] Using password 19920427
[=] Default configuration block 000880E0

[=] Begin wiping...
[=] Writing page 0  block: 00  data: 0x000880E0 pwd: 0x19920427
[=] Writing page 0  block: 01  data: 0x00000000 
[=] Writing page 0  block: 02  data: 0x00000000 
[=] Writing page 0  block: 03  data: 0x00000000 
[=] Writing page 0  block: 04  data: 0x00000000 
[=] Writing page 0  block: 05  data: 0x00000000 
[=] Writing page 0  block: 06  data: 0x00000000 
[=] Writing page 0  block: 07  data: 0x00000000 
[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[-] ⛔ No known 125/134 kHz tags found!
[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands

It looks like we change something on the card. Assuming the card is now wiped, lets try to detect it again then dump its contents (without the password).

[usb] pm3 --> lf t55xx detect
[=]      Chip Type      : T55x7
[=]      Modulation     : ASK
[=]      Bit Rate       : 2 - RF/32
[=]      Inverted       : No
[=]      Offset         : 33
[=]      Seq. Term.     : Yes
[=]      Block0         : 0x000880E0 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : No

[usb] pm3 --> lf t55xx dump
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 000880E0 | 00000000000010001000000011100000 | ....
[+]  01 | 00000000 | 00000000000000000000000000000000 | ....
[+]  02 | 00000000 | 00000000000000000000000000000000 | ....
[+]  03 | 00000000 | 00000000000000000000000000000000 | ....
[+]  04 | 00000000 | 00000000000000000000000000000000 | ....
[+]  05 | 00000000 | 00000000000000000000000000000000 | ....
[+]  06 | 00000000 | 00000000000000000000000000000000 | ....
[+]  07 | 00000000 | 00000000000000000000000000000000 | ....
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 000880E0 | 00000000000010001000000011100000 | ....
[+]  01 | E01500D0 | 11100000000101010000000011010000 | ....
[+]  02 | 3075F62B | 00110000011101011111011000101011 | 0u.+
[+]  03 | 00A00003 | 00000000101000000000000000000011 | ....
[+] saved to json file lf-t55xx-dump.json
[+] saved 12 blocks to text file lf-t55xx-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-dump.bin

Looks like the card is now blank (without a password) so we are free to use it as we please. Notice the modulation is also now default, hence why we needed to run detect first before the dump so the Proxmark3 knows which modulation to use. These programmable chips (like the T55x7 or EM4x05 series chips) are special in a way in that they can emulate a number of modulations depending on which card it is emulating. Not all chips can be programmed or reprogrammed.

One other method I would like to discuss is a slightly faster method that can be tried to recover the password. This method only worked because we have the device that set the password in our hands and we could examine the password it is sending with the Proxmark3. The Promark3 can also brute force the password which can take a while, however, a lot of these Chinese copier’s passwords are well known and common so the Proxmark3 has a script that will try all the common known passwords. Here is how that works below, it so happens this Chinese copier uses one of the well knows passwords.

I again copied the card with the Chinese copier, then tried the brute force method below.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx chk
[=] press 'enter' to cancel the command

[+] loaded 112 keys from dictionary file /Users/user/Documents/dev_proxmark3/repo/proxmark3/client/dictionaries/t55xx_default_pwds.dic
[=] press 'enter' to cancel the command
[=] testing 51243648
[=] testing 000D8787
[=] testing 19920427
[=]      Chip Type      : T55x7
[=]      Modulation     : FSK2a
[=]      Bit Rate       : 4 - RF/50
[=]      Inverted       : Yes
[=]      Offset         : 33
[=]      Seq. Term.     : No
[=]      Block0         : 0x00107070 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : Yes
[=]      Password       : 19920427

[+] found valid password: [ 19920427 ]

[+] time in check pwd 1 seconds

We were able to find the password easily with just trying common passwords with the “lf t55xx chk” command. Since we know the password we can go ahead and dump or wipe the card as shown above.

Hope this has been helpful to recover passwords set from an RFID copier.

Reading FeliCa RFID with a RC-S620S and Arduino

FeliCa reader project

After some more playing around with RFID tags and trying to read some FeliCa tags with the Proxmark3 it was obvious I needed a reader designed for FeliCa.  FeliCa was designed by SONY and has a very long history of usage starting in the 1990’s and beginning wide use in 2001 with the SUICA prepaid rail card.  It is similar to a ISO/IEC 14443, and is closer to a ISO/IEC 18092 (Near Field Communication, NFC TYPE-F) in its communications but its specification actually follows specification JIS: X6319-4.

The card offers very high level encryption and security, I have not seen a single instance of it being hacked even after all these years (yet).

To read the card and get the card id, called the IDm, I found a RC-S620S FeliCa reader at the local shop and searched around to see if anyone had attempted to connect it up to an Arduino platform.  Not suppressing I found some information on this site below with some sample Arduino code.

https://deviceplus.jp/hobby/entry_f02/

With this information I used the Arduino platform to successfully retrieve the IDm from various FeliCa cards in my possession.  After this, I found out that it is not that difficult to retrieve the current balance of the electronic money on the card as well after running across the following below site.  FeliCa is very commonly used in Japan and this can retrieve the unique 8 byte card id (IDm) and balance information for Suica, Icoca, PiTaPa, nanao, edy, and others.

https://www.orsx.net/archives/3835

I then proceeded to create a reader with an OLED display to display the IDm of the card along with the remaining electronic money balance.  This uses an Arduino Feather M0 basic along with a 128×64 OLED display to show the results.  Surprisingly, SONY released an Arduino library for the RC-S620S, which is still up on their website for download, but needs a few fixes since it is from so many years back (2000).

http://blog.felicalauncher.com/sdk_for_air/?page_id=2699

Download the above library and place it in the Arduino “libraries” folder.  In the file “RCS620S.cpp” the following changes need to be made.

Line Search for Replace with
10 #include “Wprogram.h” #include “Arduino.h”
312 Serial.write(data, len); Serial1.write(data, len);
327 if (Serial.available() > 0) { if (Serial1.available() > 0) {
328 data[nread] = Serial.read(); data[nread] = Serial1.read();
338 Serial.flush(); Serial1.flush();

The following hardware items were used in this project:

Adafruit Feather M0 Basic Proto – ATSAMD21 Cortex M0
+ https://www.adafruit.com/product/2772
Adafruit FeatherWing OLED – 128×64 OLED Add-on For Feather
+ https://www.adafruit.com/product/4650
FeatherWing Tripler Mini Kit – Prototyping Add-on For Feathers
+ https://www.adafruit.com/product/3417
NFC FeliCa Reader/Writer Module RC-S620/S
+ https://international.switch-science.com/catalog/353/
FeliCa RC-S620/S and FeliCa Link RC-S730 pitch converter board set (with flat cable)
+ https://international.switch-science.com/catalog/1029/

Here is the pinout of the RC-S602S.  It can work on either 3.3V or 5.0V.  Connect to the “uart1” of the Arduino device being used.  In the case of the Adafruit Feather m0 Basic this is D0 (UART1 RX) and D1 (UART1 TD).  There are two grounds, connect them both to ground.  The RC-S620S can be powered by 5.0v or 3.3v.  An Arduino Uno would work, but it has only one hardware UART, the softserial won’t be able to keep up with the 115200 BAUD of the RC-S620S.  I believe the limit for the softserial is around 9600 or 19200.

Connect the flat cable as shown here in the picture.

RC-S620S flat cable

RC-S620S

RC-S620S pinout

pin color description
1 red VCC (5v or 3.3v)
2 green RXD
3 white TXD
4 black GND
5 n/c do not connect, reserved
6 black GND

A version with the OLED display functions is in the below ZIP file, it is rather big to copy paste here.  Credit for the parts that I copy pasted is these two sources below.

https://deviceplus.jp/hobby/entry_f02/
https://www.orsx.net/archives/3835

https://www.drassal.net/filestore/m0_felica_oled_20210209.zip

The following code is a very simple serial only version that can be pasted.  A zip fie is also available to download.

https://www.drassal.net/filestore/m0_felica_uart_20210209.zip

#include <RCS620S.h>

#define COMMAND_TIMEOUT               400
#define POLLING_INTERVAL              500
#define RCS620S_MAX_CARD_RESPONSE_LEN 30

// FeliCa Service/System Code
#define CYBERNE_SYSTEM_CODE           0x0003
#define COMMON_SYSTEM_CODE            0xFE00
#define PASSNET_SERVICE_CODE          0x090F
#define EDY_SERVICE_CODE              0x170F
#define NANACO_SERVICE_CODE           0x564F
#define WAON_SERVICE_CODE             0x680B

RCS620S rcs620s;

// UNO
#define SERIAL_DEBUG Serial
// Due
// #define SERIAL_DEBUG SerialUSB

void setup() {
  int ret;
  while (!Serial && millis() < 10000);
  Serial.begin(115200);
  Serial.println("Serial init done!");

  // RC-S620Sの初期化
  Serial1.begin(115200);
  Serial.println("Serial1 init done!");
  ret = rcs620s.initDevice();
  while (!ret) {}
  rcs620s.timeout = COMMAND_TIMEOUT;
  Serial.println("RC-S620S init ok");
}

void polling(void) {
  int ret;
  char temp[3];
  char cardid[17];

  // FeliCaのタッチ状態を得る
  ret = rcs620s.polling();

  // FeliCaがタッチされた場合
  if(ret) {
    // IDmを取得する
    for(int i = 0; i < 8; i++){
      sprintf(temp, "%02X", rcs620s.idm[i]);
      cardid[i * 2] = temp[0];
      cardid[(i * 2) + 1] = temp[1];
    }
    cardid[16] = 0;

    printId(cardid);
  }
  
  rcs620s.rfOff();
}

void polling_balance(void) {
  char temp[3];
  char cardid[17];
  uint32_t balance;
  uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN];
   
  rcs620s.timeout = COMMAND_TIMEOUT;
   
  // サイバネ領域
  if(rcs620s.polling(CYBERNE_SYSTEM_CODE)){
    // Suica PASMO
    if(requestService(PASSNET_SERVICE_CODE)){
      if(readEncryption(PASSNET_SERVICE_CODE, 0, buf)){
        // Little Endianで入っているPASSNETの残高を取り出す
        balance = buf[23];                  // 11 byte目
        balance = (balance << 8) + buf[22]; // 10 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;

        // 残高表示
        printBalance(cardid, "PASSNET", &balance);
      }
    }
  }
   
  // 共通領域
  else if(rcs620s.polling(COMMON_SYSTEM_CODE)){
    // Edy
    if(requestService(EDY_SERVICE_CODE)){
      if(readEncryption(EDY_SERVICE_CODE, 0, buf)){
        // Big Endianで入っているEdyの残高を取り出す
        balance = buf[26];                  // 14 byte目
        balance = (balance << 8) + buf[27]; // 15 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;

        // 残高表示
        printBalance(cardid, "Edy", &balance);
      }
    }
     
    // nanaco
    else if(requestService(NANACO_SERVICE_CODE)){
      if(readEncryption(NANACO_SERVICE_CODE, 0, buf)){
        // Big Endianで入っているNanacoの残高を取り出す
        balance = buf[17];                  // 5 byte目
        balance = (balance << 8) + buf[18]; // 6 byte目
        balance = (balance << 8) + buf[19]; // 7 byte目
        balance = (balance << 8) + buf[20]; // 8 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;
        
        // 残高表示
        printBalance(cardid, "nanaco", &balance);
      }
    }
     
    // waon
    else if(requestService(WAON_SERVICE_CODE)){
      if(readEncryption(WAON_SERVICE_CODE, 1, buf)){
        // Big Endianで入っているWaonの残高を取り出す
        balance = buf[17];                  // 21 byte目
        balance = (balance << 8) + buf[18]; // 22 byte目
        balance = (balance << 8) + buf[19]; // 23 byte目 balance = balance & 0x7FFFE0; // 残高18bit分のみ論理積で取り出す balance = balance >> 5;             // 5bit分ビットシフト

        // IDmを取得する
        for(int i = 0; i < 8; i++){ sprintf(temp, "%02X", rcs620s.idm[i]); cardid[i * 2] = temp[0]; cardid[(i * 2) + 1] = temp[1]; } cardid[16] = 0; // 残高表示 printBalance(cardid, "waon", &balance); } } } rcs620s.rfOff(); } // request service int requestService(uint16_t serviceCode){ int ret; uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN]; uint8_t responseLen = 0; buf[0] = 0x02; memcpy(buf + 1, rcs620s.idm, 8); buf[9] = 0x01; buf[10] = (uint8_t)((serviceCode >> 0) & 0xff);
  buf[11] = (uint8_t)((serviceCode >> 8) & 0xff);
 
  ret = rcs620s.cardCommand(buf, 12, buf, &responseLen);
   
  if(!ret || (responseLen != 12) || (buf[0] != 0x03) ||
      (memcmp(buf + 1, rcs620s.idm, 8) != 0) || ((buf[10] == 0xff) && (buf[11] == 0xff))) {
    return 0;
  }
 
  return 1;
}
 
int readEncryption(uint16_t serviceCode, uint8_t blockNumber, uint8_t *buf){
  int ret;
  uint8_t responseLen = 0;
   
  buf[0] = 0x06;
  memcpy(buf + 1, rcs620s.idm, 8);
  buf[9] = 0x01; // サービス数
  buf[10] = (uint8_t)((serviceCode >> 0) & 0xff);
  buf[11] = (uint8_t)((serviceCode >> 8) & 0xff);
  buf[12] = 0x01; // ブロック数
  buf[13] = 0x80;
  buf[14] = blockNumber;
 
  ret = rcs620s.cardCommand(buf, 15, buf, &responseLen);
 
  if (!ret || (responseLen != 28) || (buf[0] != 0x07) ||
      (memcmp(buf + 1, rcs620s.idm, 8) != 0)) {
    return 0;
  }
 
  return 1;
}

void printId(char *card_id){
  Serial.print("IDm      : ");
  Serial.println(card_id);
  return;
}

void printBalance(char *card_id, char *service_name, uint32_t *balance){
  char result[8];
  Serial.print("IDm      : ");
  Serial.println(card_id);

  Serial.print(" SERVICE : ");
  sprintf(result, "%u", *balance);
  Serial.println(service_name);
  
  Serial.print(" BALANCE : ");
  Serial.println(result);
  
  return;
}

void loop() {
  // put your main code here, to run repeatedly:
  //polling();
  polling_balance();
  delay(POLLING_INTERVAL);
}

RFID development with a Proxmark3 RDV4.01 – first time use on MacOs

As I am occasionally doing more and more RFID related tasks at work, and curious about the data stored on all these RFID devices that I see more and more I got ahold of a Proxmark3 RDV 4.01 to gain more insight to RFID and help out with development.

Running on MacOS am completely new to the Proxmark3, take that back, about 10 years ago I got a Proxmark3 but at the time RFID was not as wide spread and never got a change to get a lot of use out of it.  Fast forward, what really peaked my interest is the use of RFID in some interesting products such as the recently released Savi’s Workshop Handbuilt Star Wars Lightsabers at Hollywood Studios Disney World.  It is easy to find information on YouTube or search engines about the RFID use in these cool new items.

Anyway, opening up the (really nice) case, this is what the inside looks like.

Proxmark3 RDV 4.01

Proxmark3 RDV 4.01

 

It looks like I am being forced to use “brew” to do this, I am not a fan of brew because I don’t know where it is putting files and want to keep my laptop clean.  I already wiped the laptop last month to git rid of a lot of “garbage” installed by things like brew.  I created a throw away account on the laptop and going to use it to do the things that require brew.  I just finished setting up brew and wrote up the below post as I was doing it.

https://www.drassal.net/wp/index.php/2021/02/05/installing-macos-brew-without-sudo

I am following this guide to setup the proxmark3 software, and after setting up brew, it was actually quite straight forward.

Based on this guide
https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md

After entering the terminal, and setting up your path for brew (if necessary) running the following three commands should get everything automatically setup, it will take a while to download and compile so grab a drink or coffee while waiting.

brew tap RfidResearchGroup/proxmark3

If you have don’t have the “Blue Shark” accessory run this command next.
brew install proxmark3

If you do have the “Blue Shark” accessory run this command.
brew install –with-blueshark proxmark3

Go grab a drink or coffee while it runs and hopefully there are no errors.  Once this is done use the below command to update the the proxmark3 hardware.  Hold the button as the USB is connected, if the LEDs turn off when the button is released the bootloader is old, repeat the process but hold the button down through the whole bootloader update process.

pm3-flash-all

In my case I got this error message
[!!] 🚨 ====================== OBS ! ===========================================
[!!] 🚨 Note: Your bootloader does not understand the new CMD_BL_VERSION command
[!!] 🚨 It is recommended that you first update your bootloader alone,
[!!] 🚨 reboot the Proxmark3 then only update the main firmware

So, according to the guide I ran the command for updating the bootloader only.

proxmark3 /dev/tty.usbmodemiceman1 –flash –unlock-bootloader –image ~/usr/local/share/proxmark3/firmware/bootrom.elf

After it completes release the USB button, put the proxmark3 back into bootloader mode by holding the button while plugging in the USB, this time two LEDs should stay lit after releasing the button.

Proceed to update the main firmware by the following command
proxmark3 /dev/tty.usbmodemiceman1 –flash –unlock-bootloader –image ~/usr/local/share/proxmark3/firmware/fullimage.elf

Note, “fullimage.elf” refers to the main application image, not including the bootloader, confusing, but this is how the proxmark3 does it.

After this is done just to be sure you are on the right firmware version reconnect the USB without holding down the button then run the following command to enter the client.

pm3

Enjoy playing with the proxmark3!
I’ll be posting some things later about the proxmark3 as I have time to test things out with it.