Bonjour,
RFID MIFARE 1k lecture et écriture de blocs
Préambule:
Tous est dans le titre ! Il s'agit de lire et d'écrire des blocs dans une carte RFID MIFARE 1k.
Aprés avoir fait le tour des tutos on trouve pas grand chose sinon rien a part le commentaire des exemples livrés ....
Ce programme a été écrit pour programmer des notes et des tempos pour une " serinette " électronique.
On peux évidemment discuter de l'appélation serinette mais ce n'est pas le but de ce post.
Ce programme n'est pas destiné a la copie de carte RFID ni au hack de secteurs ou blocs.
(Il existe d'excellent lecteur et programme pour ca)
La programmation de l'UID a été bloquée même si c'est facilement modifiable.
Je vous invite fortement a lires des tutos sur internet.
Le programme fonctionne et a été testé sur des cartes MIFARE 1k et sur des porte clés rfid que j'ai eu dans un kit.
Avertissements:
Comme déja dit ce programme n'est pas destiné au hack et a la reproduction des cartes.
Le programme est livré tel quel et sans garanties. (je n'ai pas la prétention de passer pour un modele dans l'art de la programmation)
Forcer le programme a écrire dans un bloc que j'ai interdit ( trailer), sans savoir exactement ce qu'on fait,
entraine au mieux le blocage souvent définitif du secteur.
JE NE SUIS EN AUCUN CAS RESPONSABLE DE L'UTILISATION DU PROGRAMME ET DU BLOCAGE EVENTUEL DES CARTES !!
Cablage:
Aucun secret ni innovation : une carte uno et une carte RC522 avec le cablage qu'on vois partout dans les exemples. (je ne reviendrais pas dessus)
Le programme:
constitué de :
Ecriture_RFID.uno , RFID.h, RFID.cpp, parseur.h, parseur.cpp.
Voir a la fin du post.
les commandes:
Elles doivent etre tapée dans le moniteur série:
Vitesse 115200 bauds et pas de fin de ligne
Toutes les commandes commencent obligatoirement par < et finissent obligatoirement par >
exemple: < NCard > qui permet l'acces a une nouvelle carte
supprimer les espaces ! sans la mise en forme html du forum aime pas ... et fait disparaitre la commande
Commande autorisée
Détecter nouvelle carte
Arret lecteur
Factory Key FF
Détection d'une carte RFID
Card UID: 42 4A 1D 1F
Attente de commande
Attente nouvelle commande
certaines commandes ont des attribut qui sont séparés par | (Alt Gr 6)
exemple <RHexa|0> lecture et dump hexa du bloc 0
Commande autorisée
Lecture bloc HEXA
42 4A 1D 1F 0A 08 04 00 62 63 64 65 66 67 68 69
Attente nouvelle commande
On retrouve l'UID et le code fabricant a la fin (carte chinoise)
ou <DHexa|1|4> Dump hexa des blocs 1 a 4.
Commande autorisée
Dump bloc HEXA
2D 53 54 41 52 20 54 52 45 4B 20 44 53 20 39 2D
20 20 20 20 20 20 20 20 20 20 20 20 20 20 31 46
00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
FF 45 65 DE DF AE 12 00 ED 14 E7 A0 DD FF EA 52
On peut voir en bloc 1 une ligne aux codes correspondants a -STAR TREK DS 9-
On peut voir en bloc 3 une ligne aux codes correspondants aux Key A et B ainsi que d'autre octet que je ne commenterais pas .
(a savoir qq soit la key A la puce renvoi 6 x 00 le code est donc invisible.)
Commandes d'écriture:
exemple <WText|1|-|S|T|A|R| |T|R|E|K| |D|S| |9|-> permet d'écrire dans le bloc 1 les caractéres ASCII correspondant a -STAR TREK DS 9-
il y a bien 16 caractéres correspondant au 16 bytes contenu dans le secteur 1.
<WHexa|4|00|FF|FE|48|AE|12|26|EF|89|ED|10|DF|A0|BC|09|25> permet d'écrire les 16 valeurs exprimées en Héxadécimal.
<WDeci|8|0|255|-6|48|10|120|216|-16|89|78|10|5|126|78|09|25> permet d'écrire les 16 valeurs exprimées en Décimal.
a chaque fois le bloc est relu est réaffiché en HEXA.
Attention: S'il manque des attributs ca va écrire un peu n'importe quoi dans les vides
Identification:
elle est réalisée sur la key B (ca peut etre modifié dans le programme en Key A) avec un pass établi a FF FF FF FF FF FF mot de passe usine !
Remerciement:
je remercie tous ceux qui par leurs présences et leurs réponses font de ce forum une véritable aide.
Ils se reconnaitrons facilement.
Merci beaucoup donc.
Ecriture_RFID.ino
#include "RFID.h"
#include "parseur.h"
unsigned char writeBlockData[16];
byte bufferReadLen = 18;
unsigned char readBlockData[18];
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup() {
Serial.begin(115200);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
detection_Carte();
}
void loop() {
}
void serialEvent() {
lireCommande();
}
RFID.h
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
extern MFRC522 mfrc522;
extern unsigned char writeBlockData[16];
extern byte bufferReadLen;
extern unsigned char readBlockData[18];
bool autorisationBloc(byte bloc_num);
void factory_key();
void detection_Carte();
void lire_Bloc(byte numblock);
void ecrire_Bloc(byte numblock);
void liberer_Carte();
void dump_byte_array(byte *buffer, byte bufferSize);
RFID.cpp
#include "RFID.h"
#include "Arduino.h"
MFRC522::MIFARE_Key key;
MFRC522::StatusCode status;
void factory_key() {
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
Serial.println(F("Factory Key FF"));
}
bool autorisationBloc(byte bloc_num) {
bool autorisation = false;
if (bloc_num > 0 && (bloc_num % 4) < 3 ) {
autorisation = true;
}
return autorisation;
}
void detection_Carte() {
byte bufferWriteLen = 16;
factory_key ();
Serial.println(F("Détection d'une carte RFID"));
if ( ! mfrc522.PICC_IsNewCardPresent()) {
Serial.println(F("Pas de nouvelle carte"));
return;
}
if ( ! mfrc522.PICC_ReadCardSerial()) {
Serial.println(F("Pas de serial"));
return;
}
Serial.print(F("Card UID:")); //Dump UID
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println("");
Serial.println(F("Attente de commande"));
Serial.println("");
}
void lire_Bloc(byte numblock) {
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, numblock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(numblock, readBlockData, &bufferReadLen);
}
void ecrire_Bloc(byte numblock) {
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, numblock, &key, &(mfrc522.uid));
status = mfrc522.MIFARE_Write(numblock, writeBlockData, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
else Serial.println(F("MIFARE_Write() success: "));
}
void liberer_Carte() {
Serial.println();
Serial.println("Arret lecteur");
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
void dump_byte_array(byte * buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
Serial.println();
}
parseur.h
/*
DETECTION ET DECOMPOSITION D'UNE COMMANDE
*/
#include <stdlib.h>
#include <string.h>
#include "RFID.h"
void lireCommande();
//Accusé de reception commande
void ack_command(char *message);
//This function execute a command. Amend this function with your own commands
void exec_command();
//Parsing identifiant commande et arguments
void parse_command();
parseur.cpp
#include "Arduino.h"
#include "parseur.h"
/*DETECTION ET DECOMPOSITION D'UNE COMMANDE*/
#define MAX_CMD_LEN 80
#define MAX_ARGS_LEN 6
#define MAX_ARGS 40
const char NCard_Str[] PROGMEM = "NCard"; // Détecter nouvelle carte
// écriture avec vérification du bloc
const char WHexa_Str[] PROGMEM = "WHexa"; // Ecrire un bloc en héxadécimal
const char WDeci_Str[] PROGMEM = "WDeci"; // Ecrire un bloc en décimal
const char WText_Str[] PROGMEM = "WText"; // Ecrire un bloc en texte
// Lecture d'un bloc
const char RHexa_Str[] PROGMEM = "RHexa"; // Lire un bloc en héxadécimal
const char DHexa_Str[] PROGMEM = "DHexa"; // Dump des blocs en héxadécimal
const char *const Command_List[] PROGMEM = {NCard_Str, WHexa_Str, WDeci_Str, WText_Str, RHexa_Str, DHexa_Str};
const byte NB_COMMANDS = sizeof(Command_List) / sizeof(Command_List[0]);
enum Command_IDs : byte {
NCard = 0,
WHexa = 1,
WDeci = 2,
WText = 3,
RHexa = 4,
DHexa = 5
};
//Reception commande
int Command_ID;
char arg_list[MAX_ARGS][MAX_ARGS_LEN];
char incomingByte;
int command_index = 0;
char command_line[MAX_CMD_LEN];
int iPrintConfirmation;
void(* resetFunc) (void) = 0; // adresse de fonction reset;
void lireCommande() {
static byte CmdOk = 0;
if (Serial.available()) {
incomingByte = Serial.read();
//Serial.println(incomingByte);
switch (incomingByte)
{
case '<':
CmdOk = 1;
command_index = 0;
memset(command_line, 0, MAX_CMD_LEN - 1);
break;
case '>':
CmdOk = 0;
command_line[command_index + 1] = 0;
parse_command();
exec_command();
break;
default :
if ((CmdOk == 1) && (command_index < MAX_CMD_LEN)) {
command_line[command_index++] = incomingByte;
}
}
} // Serial.println(command_line);
}
//Accusé de reception commande
void ack_command(char *message)
{
//iPrintConfirmation =1;
if (iPrintConfirmation > 0)
{
Serial.print(F("Command executée : "));
Serial.print((const __FlashStringHelper *)pgm_read_word(&Command_List[Command_ID]));
Serial.print("->");
Serial.print(message);
Serial.println();
}
}
//execution des commandes
void exec_command()
{
byte bloc;
switch (Command_ID)
{
case NCard:
Serial.println(F("Détecter nouvelle carte"));
liberer_Carte();
delay(500);
detection_Carte();
break;
case WHexa:
Serial.println(F("Ecrire bloc HEXA"));
bloc = atoi(arg_list[1]);
if (autorisationBloc(bloc)) {
Serial.println(F("Ecriture autorisée"));
for (int i = 0; i < 16; i++) {
byte val = strtoul (arg_list[i + 2], nullptr, 16);
writeBlockData[i] = val;
}
dump_byte_array(writeBlockData, 16);
// transfert et ecriture ....
ecrire_Bloc(bloc);
Serial.println(F("Relecture du bloc"));
lire_Bloc(bloc);
dump_byte_array(readBlockData, 16);
} else {
Serial.print(F("Ecriture interdite bloc : "));
Serial.println(bloc);
}
break;
case WDeci:
Serial.println(F("Ecrire bloc DECI"));
bloc = atoi(arg_list[1]);
if (autorisationBloc(bloc)) {
Serial.println(F("Ecriture autorisée"));
for (int i = 0; i < 16; i++) {
byte val = atoi(arg_list[i + 2]);
writeBlockData[i] = val;
}
dump_byte_array(writeBlockData, 16);
// transfert et ecriture ....
ecrire_Bloc(bloc);
Serial.println(F("Relecture du bloc"));
lire_Bloc(bloc);
dump_byte_array(readBlockData, 16);
} else {
Serial.print(F("Ecriture interdite bloc : "));
Serial.println(bloc);
}
break;
case WText:
Serial.println(F("Ecrire bloc TEXT"));
bloc = atoi(arg_list[1]);
if (autorisationBloc(bloc)) {
Serial.println(F("Ecriture autorisée"));
// transfert et ecriture ....
for (int i = 0; i < 16; i++) {
writeBlockData[i] = 0;
}
dump_byte_array(writeBlockData, 16);
for (int i = 0; i < 16; i++) {
writeBlockData[i] = (byte) * arg_list[i + 2];
}
dump_byte_array(writeBlockData, 16);
ecrire_Bloc(bloc);
Serial.println(F("Relecture du bloc"));
lire_Bloc(bloc);
dump_byte_array(readBlockData, 16);
} else {
Serial.print(F("Ecriture interdite bloc : "));
Serial.println(bloc);
}
break;
case RHexa:
Serial.println(F("Lecture bloc HEXA"));
bloc = atoi(arg_list[1]);
lire_Bloc(bloc);
dump_byte_array(readBlockData, 16);
break;
case DHexa:
Serial.println(F("Dump bloc HEXA"));
byte blocd = atoi(arg_list[1]);
byte bloca = atoi(arg_list[2]);
for (byte bloc = blocd; bloc < bloca + 1; bloc++) {
lire_Bloc(bloc);
dump_byte_array(readBlockData, 16);
}
break;
default :
Serial.print(F("Erreur commande -> "));
Serial.println(command_line);
break;
}
Command_ID = -1;
Serial.println();
Serial.println(F("*******************"));
Serial.println(F("Attente nouvelle commande"));
}
//Parsing identifiant commande et arguments
void parse_command()
{
char * pch;
int ii = 0;
//parsing et Identification des attributs
pch = strtok (command_line, "|");
while (pch != NULL)
{
strcpy(arg_list[ii], pch);
pch = strtok (NULL, "|");
//Serial.print(arg_list[ii]);Serial.print("--");Serial.println(ii);
ii++;
}
//identification de l'ID
Command_ID = -1;
for (ii = 0; ii < NB_COMMANDS; ii++)
{
//Serial.print("Comparaison de <"); Serial.print((const __FlashStringHelper *)pgm_read_word(&Command_List[ii])); Serial.print("> et de <");
//Serial.print(arg_list[0]); Serial.println(">");
if (strcmp_P(arg_list[0], pgm_read_word(&Command_List[ii])) == 0)
{
Command_ID = ii;
Serial.println("Commande autorisée");
break;
}
}
}