Skyduino:~#
Articles
Corrigé, programmation, projet, python

[hack] Lecteur RFID chinois – Huge success

Bonjour à tous !

This was a triumph.
I’m making a note here: HUGE SUCCESS
It’s hard to overstate my satisfaction.

~~ musique de Portal ~~

Pourquoi cet article alors que j’ai déjà parlé du lecteur RFID chinois dans l’article juste avant ?
Pourquoi je commence cet article avec une référence à Portal ?
Pourquoi *BAM* … aie

Plus sérieusement, je fais cet article pour remercier toutes les personnes qui m’ont aidé (ou qui ont essayé) à « hacker » le lecteur :
Damien
Guigui
blakk-olifant
Adrien
Simon
Guillaume
– et Antafuli

Sans eux je serais encore en train de chercher comment décoder les trames du lecteur …
La méthode de codage des IDs RFID était barbare, plutôt loufoque sur les bords, mais ça ne les a pas arrêtez pour autant 🙂

Et maintenant que j’ai toutes les cartes en main je vais pouvoir vous faire un résumé rapide 😉

La documentation du lecteur :

Elle était bien caché au fin fond d’un site de vente chinois plus ou moins recommandable mais la voici :
(j’ai fait un miroir du pdf sur mon compte dropbox par sécurité)
https://dl.dropbox.com/u/53604363/USB%20Desktop%20Reader_BlackBox%20D10.pdf

Je vous laisse la feuilleter rapidement, je repasserai sur les points importants dans la suite de l’article.

Est-ce que le lecteur peut lire des cartes HID / iProx ?

Le site du fabricant dit que oui, la documentation aussi …
Je n’ai pas pu tester malheureusement (je n’ai tout simplement pas de carte HID sous la main), donc pour le moment la question reste sans réponse.
Théoriquement rien n’empêche le lecteur de gérer deux protocoles RFID 125KHz différents donc pourquoi pas …

Est-ce que le lecteur peut aussi programmer des cartes HID / iProx / EM4100-RW ?

Toujours d’après le site du fabricant et de la documentation : oui
Est-ce que cela est vraiment possible : … je sais pas non plus !

Comme on peut le voir dans la documentation le lecteur semble ce comporter comme un port série usb (chipset CH34x).
Et une application nommée « iProxCard Programmer » s’occupe de la programmation des cartes iProx.

Mon lecteur lui ne se comporte que comme un clavier usb … ce qui me laisse vraiment penser qu’il existe deux versions différentes du même lecteur :
– une haut de gamme (lecture / écriture en mode port série usb)
– et une bas de gamme (lecture seule en mode clavier usb)

Mais c’est pas tout !

En y regardant de plus près avec un PC linux on remarque quelque chose de spécial concernant l’usb :
skywodd@skywodd-eeepc /dev $ tail /var/log/kern.log
Feb 5 19:27:57 skywodd-eeepc kernel: [ 434.260120] usb 2-2: >new low-speed USB device number 4 using uhci_hcd
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.506143] usb 2-2: >New USB device found, idVendor=08ff, idProduct=0009
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.506156] usb 2-2: >New USB device strings: Mfr=1, Product=1, SerialNumber=2
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.506166] usb 2-2: >Product: USB Reader With Keyboard
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.506175] usb 2-2: >Manufacturer: USB Reader With Keyboard
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.506184] usb 2-2: >SerialNumber: FM8PU83-Ver0E-0000
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.532967] input: USB Reader With Keyboard USB Reader With Keyboard as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input14
Feb 5 19:27:58 skywodd-eeepc kernel: [ 434.533460] hid-generic 0003:08FF:0009.0003: >input,hidraw0: USB HID v1.10 Keyboard [USB Reader With Keyboard USB Reader With Keyboard] on usb-0000:00:1d.0-2/input0

Pour le moment rien de bien extraordinaire, c’est un clavier usb … rien de plus …

Sauf que, un lsusb plus tard …
skywodd@skywodd-eeepc /dev $ lsusb
Bus 002 Device 005: ID 08ff:0009 AuthenTec, Inc. <---------- HoHoHo !
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Ça vous dit rien AuthenTec ?
C’est une société spécialisé dans les lecteurs d’empreintes digitales racheté par Apple en novembre dernier.

Apparemment il faisaient des chipsets usb pour lecteur RFID par le passé et je ne suis pas le seul à avoir remarquer la chose :
http://wiki.techinc.nl/index.php/AuthenTec-RFID-reader
(dommage qu’il n’y ait pas plus d’information sur ce wiki …)

Bref, savoir qui a réellement fabriqué quoi n’est pas le plus important.
Le plus important c’est de savoir comment interpréter les données émises par le lecteur !

Un début de réponse se trouve ici (merci Guillaume pour le lien) :
http://www.ardushop.com/kits/electronic-brick-125khz-rfid-card-reader.html

En y regardant bien le lecteur du lien ci-dessus retourne 10 octets de données, calés entre un entête et une checksum.
Si on applique le même algorithme avec les données du lecteur « BlackBox » … miracle, ça marche (merci Antafuli pour les calculs) !

Comment c’est codé et comment on décode tout ça ?

Préparez un tube d’aspirine ça va faire mal à la tête …

D’habitude les chinois font au plus simple et au moins chère, pour le coup c’est pas du tout le cas !
L’algorithme de codage / décodage est complètement tiré par les cheveux …

Partons de l’ID (en hexadécimal) d’une carte RFID connu (une carte Parallax pour le coup) :
26 00 D7 18 74

La première étape consiste à supprimer l’octet de poids fort (le premier octet en partant de la gauche) :
00 D7 18 74

La seconde étape consiste à convertir ce chiffre hexadécimal en une valeur décimal (passage de la base 16 à la base 10 pour les matheux) :
0xD71874 = 14096500

Ajoutez ensuite quelques zéro sur la gauche pour avoir 10 chiffres :
0014096500

Et pour finir passer chaque chiffre à la moulinette, en utilisant ce tableau :
0 = E0
1 = 26
2 = E9
3 = 22
4 = 27
5 = 28
6 = 2D
7 = E8
8 = 5F
9 = E7

(ne me demandez où est la logique dans cette suite de chiffre je n’ai même pas cherché)
(EDIT: ce sont les scan code des chiffres 0 à 9 des claviers qwerty)
(ces valeurs ont était vérifiés avec mon spoofer RFID et des ID calculés spécialement pour avoir chaque digit séparément)

Pour cet exemple on obtient :
0 0 1 4 0 9 6 5 0 0
E0 E0 26 27 E0 E7 2D 28 E0 E0

Si on passe cette carte sur le lecteur (pour vérifier) et que l’on affiche les frappes du clavier en hexa :

hexa

C’est la même trame que notre calcul !

Vous vous demandez sûrement pourquoi ils n’ont pas tout simplement envoyé l’ID du tag en hexa sans ce poser de question ?
Et bien je me pose la même question !
Le fait est qu’avec le système actuel un octet de l’ID du tag est perdu, réduisant grandement le nombre de combinaisons possibles sans conflit d’ID …

Un petit script pour automatiser tout ça :

En python (on change pas les bonnes habitudes) :

# Blackbox D9 RFID reader data decoder

# Convertie une chaîne de caractères hexa séparés par des espaces en une valeur brute
def hexa_to_rawID(hexStr):
    hexStr = ''.join(hexStr.split())
    return int(hexStr, 16)

# Convertie une valeur brute en une valeur "tronquée"
def rawID_to_semiID(rawID):
    return int(rawID) & 0xFFFFFFFF

# Encode une valeur "tronquée" en une chaîne hexa comme celle que donnerait le lecteur
def semiID_to_rfid(semiID):
    convTable = {'0':'E0', '1':'26', '2':'E9', '3':'22', '4':'27', '5':'28', '6':'2D', '7':'E8', '8':'5F', '9':'E7'}
    res = []
    for c in str(int(semiID)).zfill(10):
        res.append(convTable[c])
    return ' '.join(res)

# Converti un tableau de données binaire en une chaine de caractéres hexa
def binary_to_rfid(binary):
    res = []
    for byte in binary:
        byte = ord(byte)
        res.append(hex(byte)[-2:].upper())
    return ' '.join(res)

# Décode une chaine hexa généré par le lecteur en une valeur "tronquée"
def rfid_to_semiID(rawRFID):
    rconvTable = {'E0':'0', '26':'1', 'E9':'2', '22':'3', '27':'4', '28':'5', '2D':'6', 'E8':'7', '5F':'8', 'E7':'9'}
    res = ''
    for v in rawRFID.split():
        res += rconvTable[v]
    return int(res, 10)

# ID des tags de test
tagIDs = [
    '26 00 D7 18 74',
    '26 00 D6 F1 A8',
    '01 07 DD 76 72',
    '01 07 DD 72 75',
    '01 07 DD 59 3B',
    '01 07 DD 74 95',
    '01 07 DD 79 11' ]

# Valeurs lu pour chacun des tags de test
readIDs = [
    'E0 E0 26 27 E0 E7 2D 28 E0 E0',
    'E0 E0 26 27 E0 5F 2D 28 2D 5F',
    'E0 26 22 26 E7 28 27 E9 E7 E0',
    'E0 26 22 26 E7 28 22 26 5F E7',
    'E0 26 22 26 E7 27 2D 5F 26 26',
    'E0 26 22 26 E7 28 22 5F 26 22',
    'E0 26 22 26 E7 28 27 E7 2D 26' ]

# Calcul de chaque tags
for i in range(0, len(tagIDs)):
    tagID = tagIDs[i]
    print 'Real ID:', tagID # ID réel
    rawID = hexa_to_rawID(tagID)
    print 'Raw ID:', hex(rawID).strip('L') # ID réel en valeur brute
    semiID = rawID_to_semiID(rawID)
    print 'Semi ID:', hex(semiID).strip('L') # ID tronqué
    rfid = semiID_to_rfid(semiID)
    print 'RFID ID:', rfid # ID encodé
    print 'RFID ID:', readIDs[i] # ID réelement lu (doit être identique que la ligne au dessus)
    semiID = rfid_to_semiID(rfid)
    print 'Semi ID:', hex(semiID).strip('L') # ID (re)décodé

# Démonstration du décodage depuis un tableau de données binaire (les même principe est applicable avec stdin)
binary = '\xE0\xE0\x26\x27\xE0\xE7\x2D\x28\xE0\xE0'
rfid = binary_to_rfid(binary)
semiID = rfid_to_semiID(rfid)
print hex(semiID)[2:].zfill(10)

Bon bidouillage à tous !

Discussion

15 réflexions sur “[hack] Lecteur RFID chinois – Huge success

  1. Brillant ! 😉
    content d’avoir pu t’aider !

    Publié par Guillaume | 8 février 2013, 22 h 31 min
  2. Marrant, j’ai le même lecteur (enfin, vu de l’exterieur), que j’ai trouvé sur ebay pour une somme ridicule. Il me semblait que celui que je possède envoie les scan codes des touches 1 à 0. Or sur les claviers qwerty, les chiffres sont la configuration par défaut et les symboles sont atteint avec shift (l’inverse des claviers azerty, quoi!) Donc il suffisait de translater les caractères recus en chiffres correspondant on retrouvait l’id de la carte….

    Félicitations pour ta publication sur hackaday!

    Publié par Vorian | 16 février 2013, 17 h 07 min
    • Je viens de tester en clavier qwerty … la table de correspondance concorde effectivement avec les scan code des touches 0 à 9 …

      J’ai ajouté un édit à mon article du coup 😉
      (raaa je me suis cassé la tête à vérifier chaque digit un à un alors que c’était un truc tout con !)

      >> Félicitations pour ta publication sur hackaday!

      Merci 🙂

      Publié par skywodd | 16 février 2013, 17 h 18 min
      • Bonjour,

        J’ai eu le même problème avec un lecteur de piste magnétique low-cost (MSR90).

        En fait, l’appareil propose une emulation clavier US ou un emulation des codes ASCII (alt +).

        J’allais donc te proposer la solution que j’ai retenu car fonctionnant sur Windows comme sur Linux (et donc Android), à savoir changer le mappage clavier (keyboard layout) pour English US. Mais bon je viens de voir que la solution a déjà été trouvée…

        Bonne continuation,
        Tom

        Publié par souvignet | 17 février 2013, 11 h 34 min
      • hello,

        c’est super facile à dire après coup. mais l’extrait qu’on voit dans la copie d’écran de HxD fait rapidement penser aux chiffres d’un clavier AZERTY sans le shift 🙂

        Publié par domi | 17 février 2013, 12 h 01 min
  3. ils utilisent surement un encodage pour satisfaire aux exigences des entreprises sousieuse de leur securitée (et de leur porte monnais aussi)

    Publié par yui | 20 mars 2013, 23 h 26 min
  4. Excusez-moi s’il te plait, pour encrir en englais 🙂

    Thank you very much for this very enjoyable article. I’m only a rookie at all of this RFID stuff, but your article is both understandable and funnily written.

    > Comment c’est codé et comment on décode tout ça ?
    > Préparez un tube d’aspirine ça va faire mal à la tête …

    Seriously, it’s stuff like that which makes me A) follow your blog from now on B) want to read more tech stuff in french 🙂

    Cheers!

    Publié par Cailin Coilleach | 10 juin 2013, 13 h 39 min
  5. Have you had any luck, or tried using this with libnfc? http://nfc-tools.org/index.php?title=Main_Page
    I bought this on ebay, after looking at 4 or 5 different ones, none of them listing chipsets or anything so I went for the only one that didn’t list itself as a « virtual keyboard » in the description, I guess I was wrong.

    If I plug it in, I get all the same output as yours, but if I run nfc-list I get a « No NFC device found. », and it seems no one on the internet has information about this reader.

    Any ideas? Thanks

    Publié par azkayay | 14 juin 2013, 4 h 50 min
    • Please excuse my terrible English it’s definitely not my piece of cake 🙂

      NFC and RFID are not the same technology, nor the same protocol.
      RFID is read-only and operate at a frequency of 125KHz (generally speaking), that perfect for wireless device identification.
      NFC is read-write and bi-directional, it’s operate at 13.56MHz and allow medium-speed data transfer between two devices. It’s clearly not the same usage (identification vs communication).

      Libnfc is compatible with NFC chipset (that sound logical …) but not with RFID chipset because, well, that not the same things. Yes it’s wireless but it’s two different technology and use case.

      Publié par skywodd | 14 juin 2013, 20 h 40 min
      • Thanks for the response, feel free to type in french. I can read it fine, I just can’t type it.

        This is where I got it: http://www.ebay.com.au/itm/360528741117 it was advertised as 13.56mhz Mifare reader, so I assumed it would work as a reader.

        Oh well, I guess I’ll need to spend more money.

        Publié par azkayay | 14 juin 2013, 20 h 55 min
      • Les tags MiFARE et NFC utilisent la même fréquence (13.56MHz) mais pas le même protocole.
        Les tags MiFARE sont des tags RFID améliorés qu’on peut lire/écrire (mémoire EEPROM).

        Les lecteurs NFC sont rétro-compatible avec les tags MiFARE (même fréquence juste une extension du protocole) mais les lecteurs MiFARE ne peuvent pas faire de NFC.
        Pour faire des communications NFC il faut un vrai lecteur NFC, tout simplement.

        Publié par skywodd | 15 juin 2013, 14 h 56 min
  6. J’ai recu mon petit lecteur ( commandé suite çà cette article )
    par contre je n’ai pas trouver la maniere de récupérer l’entree keyboard du lecteur pour la passer dans la fonction
    je ne maitrise pas vraiment le python 🙂
    j’ai regardé un peu du cote de evdev mais bon sans grand succes jusque ici

    Si vous pouviez m’aider un peu 🙂

    Publié par tanguy | 14 juin 2013, 8 h 41 min
    • Simple, c’est un clavier …
      Tu ouvres un éditeur hexa, tu colles ton curseur dans la fenêtre d’édition et tu passes ton tag.

      Si tu veut faire plus simple passe ton clavier en mode QWERTY et *magie* le lecteur sortira des chiffres directement sur le clavier.

      Publié par skywodd | 14 juin 2013, 20 h 43 min
  7. Il y a deux ans (mars 2013) je parcourais frénétiquement les forums pour trouver des informations sur les lecteur RFID chinois. Et enfin grâce a cette article j’ai pu décoder mes badges.

    Aujourd’hui, j’ai retrouvé un lecteur RFID que j’ai branché machinalement sur ma tablette, 2 bips de validation m’on confirmé que le lecteur était reconnu.
    J’ai ouvert ma messagerie en mode écriture, un bref passage du badge sur le lecteur et comme par magie le code s’est affiché.
    c’est beau la technique.

    Publié par MERCK | 25 février 2015, 19 h 16 min

Rétroliens/Pings

  1. Pingback: Turning an $8 RFID reader into something useful - 16 février 2013

Skyduino devient Carnet du Maker

Le site Carnet du Maker remplace désormais le blog Skyduino pour tout ce qui touche à l'Arduino, l'informatique et au DIY.