HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Электроника и Фрикинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 13.02.2020, 19:23
powermetall
Новичок
Регистрация: 12.02.2020
Сообщений: 5
С нами: 3290343

Репутация: 0
По умолчанию

Собираем донгл для работы с бесконтактными картами

Вступление
Бесконтактные карты давно уже стали неотъемлемой частью нашей жизни. С их помощью мы проходим на работу, пользуемся общественным транспортом, используем в качестве ключей. В этой статье я предлагаю подробно рассмотреть как теоретические основы работы бесконтактных карт, так и на практике собрать устройство для чтения и записи данных на карты. В качестве аппаратной платформы нам потребуется Arduino Nano и модуль для считывания прошивок, а также переходник miniUSB-microUSB/Type C для взаимодействия со смартфоном.
В статье речь пойдет о низкоуровневой работе с картами диапазона 13,56 МГц на уровне байт. Поэтому я не буду касаться технологии NFC и функционала смартфонов по работе с картами через NFC с помощью приложений типа NFC ReTag.
Описанные в статье решения и технологии могут быть полезны как системным администраторам и сотрудникам служб безопасности, отвечающим за пропускной режим на объекте, так и специалистам по ИБ, осуществляющим тестирования на проникновение.
Однако, как обычно напоминаю, что вся информация, представленная в статье приводится исключительно с ознакомительной целью. По этой же причине я сознательно опускаю реализацию части функций в описываемом устройстве.
Теория бесконтактных карт
В этом разделе мы поговорим о том, какие бывают карты. Бесконтактные карты бывают двух диапазонов 125 кГц, и 13,56 МГц (более экзотические диапазоны рассматривать не будем) и действуют на расстоянии от 0 до 15 см. Принцип действия построен на использовании колебательного контура, базовыми компонентами которого являются микросхема, конденсатор и катушка индуктивности.
Считыватель излучает магнитное поле с помощью катушки индуктивности, тем самым передавая ток и заряжая конденсатор, который питает электроэнергией микросхему. Обмен информацией между картой и считывающим устройством осуществляется через эту же катушку посредством модуляции колебаний электромагнитного поля устройства. В простейшем случае карта циклически непрерывно передаёт только свой уникальный номер. Однако, как мы увидим далее, возможен и более сложный обмен информацией по принципу запрос-ответ. Многие карты обладают небольшой флеш-памятью порядка 1 Кб, в которую можно записывать данные.
Далее речь пойдет только о 13,56 МГц, так как карты диапазона 125 КГц считаются устаревшими (хотя в России активно используются) и небезопасными. Однако, если в процессе пентеста вам потребуется проверить защищенность СКУД на основе карт этого диапазона, то можно воспользоваться вот этим готовым копировальщиком:
https://aliexpress.ru/item/40002413...earchweb0_0,searchweb201602_,searchweb2 01603_
Бесконтактная карта с рабочим диапазоном 13,56 МГц представляет собой, по сути один килобайт энергонезависимой памяти. Он делится на 16 секторов по 4 16-байтных блока в каждом. Блок - наименьшая адресуемая единица при работе с картой. Сектор - единица, с которой сопоставляются отдельные права доступа и ключи для проведения операций. Каждый сектор хранит собственную пару ключей, а права доступа указывают, какой доступ при указании какого ключа возможен. Для взаимодействия с картой используется протокол PICC, позволяющий получить данные с карты.
Алгоритм активации PICC в соответствии со стандартом ISO 14443 представлен на следующем рисунке:



В результате активации PICC мы получим примерно следующие данные:
UID: 0123456789abcdefaa55

Card UID: 01 23 45 67 89 AB CD EF AA 55

Card SAK: 20

PICC type: PICC compliant with ISO/IEC 14443-4

Dumping memory contents not implemented for that PICC type.

PCD_TransceiveData status=3

00000000000000000000000000000000000000000000000000 00000000000000


Так как, при написании кода мы будем использовать библиотеку, уже содержащую реализацию всех необходимых для работы PICC операций, а не вижу смысла более подробно рассматривать процесс активации и взаимодействия по протоколу PICC. Вместо этого я предлагаю перейти к практической части. Но желающим ознакомиться с занудной теорией предлагается почитать описание протокола 14443A ( ГОСТ Р ИСО/МЭК 14443-3-2014 Карты идентификационные. Карты на интегральных схемах бесконтактные. Карты близкого действия.)
ГОСТ Р ИСО/МЭК 14443-4-2014 Карты идентификационные. Карты на интегральных схемах бесконтактные. Карты близкого действия. Часть 4. Протокол передачи, ГОСТ Р от 11 ноября 2014 года №ИСО/МЭК 14443-4-2014

Концепция донглов
Мы привыкли к тому, что любое устройство должно быть самодостаточным. Заряженный телефон, планшет, ноутбук все эти устройства являются самодостаточными и будучи заряженными не требуют каких-либо дополнительных аппаратных компонентов для работы. Другое дело, это самодельные устройства, заточенные под выполнение конкретных задач. Для взаимодействия с пользователем им нужны кнопки, выключатели, дисплей (хотя бы ЖК), источник питания. Все это усложняет конструкцию, (необходимо использовать большее число деталей, паять больше контактов) создает больше точек отказа (может отказать больше деталей и контактов), увеличивает габариты и массу устройства (для портативного устройства размеры имеют значение), наконец увеличивают стоимость реализации (стоимость ЖК дисплея вместе с аккумулятором и модулем управления питанием и корпусом большего размера будет больше стоимости Ардуины).
Теперь вспомним что у любого из нас всегда есть с собой смартфон, который может предоставить все необходимые ресурсы (интерфейс взаимодействия, питание) для нашего устройства.
Слово dongle англоязычная википедия трактует как устройство, которое будучи подключенным к порту другого устройства предоставляет ему дополнительную функциональность. Предлагаю более пристально посмотреть на концепцию устройств, подключаемых к смартфонам. Такая концепция существенно упрощает сборку и повышает надежность, не требуя взамен серьезных ресурсов от смартфона. Достаточно лишь через переходник USB-microUSB или type-C (зависит от смартфона) подключить донгл и с помощью USB-Serial клиента управлять им. В своих последующих статьях я планирую еще не раз использовать донглы для различных задач.
Приступаем к сборке
Четко сформулируем требования и приступим к сборке. Итак, наше устройство должно подключаться через microUSB/type-C к телефону. В приложении USB-Serial мы подключаемся к нужному порту. Далее должно открыться меню, в котором мы можем выбрать нужный режим.
Предлагается реализовать следующие режимы:
  1. Чтение содержимого карты
  2. Чтение персональных данных с карты
  3. Запись персональных данных на карту
Отличие первого от второго пунктов заключается в том, что в первом случае мы читаем все данные с карты (делаем дамп), тогда, как во втором мы считываем только значения полей, в которые записываются данные владельца карты, как правило имя и фамилия.
Вот что выдадут для одной и той же карты выбор первого и второго пунктов:

Для сборки демонстрационного устройства данного функционала вполне хватит. Теперь, поговорим о том, какие компоненты нам потребуются. Вот все что нужно:
  1. Arduino Nano (с не припаянными разъемами) – https://aliexpress.ru/item/32341832...earchweb0_0,searchweb201602_,searchweb2 01603_
  2. Модуль MFRC-522 - https://aliexpress.ru/item/32946922...earchweb0_0,searchweb201602_,searchweb2 01603_
  3. Переходник miniUSB->microUSB/Typec-C
В качестве ядра устройства будет выступать Arduino Nano. Я крайне не рекомендую использовать более мощные Ардуины по нескольким причинам. Прежде всего, для наших задач Nano вполне достаточно, так как мы делаем портативное устройство и размер имеет большое значение, а Nano достаточно маленькая. Также, Arduino Nano можно приобрести с не припаянными штекерами. В готовых к использованию устройствах я никогда не использую беспаечные соединения, так как их надежность в боевых условиях стремится к нулю. Беспаечные платы хороши только для быстрого прототипирования. Для реальных устройств только паяльник. Не поленитесь научиться нормально паять – навык в хозяйстве пригодится.
К Arduino необходимо припаять модуль для работы с бесконтактными картами в соответствии со следующей схемой.



Далее нам необходимо написать прошивку для нашего донгла. В качестве средства разработки мы будем использовать среду Arduino IDE. Тем, кто вообще не знаком с Arduino, я рекомендую поискать в интернете статьи по работе с данной макетной платой, так как обучение основам не входит в рамки данной статьи.
Если вы до этого не работали с RFID, необходимые библиотеки у вас скорее всего не установлены. Поэтому перед написания кода установим необходимые библиотеки. Для этого необходимо скачать файл https://github.com/miguelbalboa/rfid/archive/master.zip и распаковать содержимое архива в папку %Arduino_IDE%/libraries. Теперь, после запуска среды Arduino IDE, у нас в разделе Files -> Examples -> MFRC522 должны появиться несколько скетчей с примерами работы с картой.
Теперь перейдем непосредственно к кодингу. Прежде всего реализуем меню для взаимодействия по Serial порту. Для этого в стандартной процедуре loop выведем на экран опции меню и будем ожидать пользовательского ввода.

C:


Код:
Serial
.
println
(
"1. Read dump the card"
)
;
Serial
.
println
(
"2. Read personal data"
)
;
Serial
.
println
(
"3. Write personal data"
)
;
В зависимости от выбранных пользователем пунктов запускаем соответствующие процедуры. Алгоритмы работы с картами построены на основе примеров, входящих в состав библиотеки MFRC522, поэтому, в случае возникновения проблем, вы можете проверить работу отдельных процедур непосредственно в примерах.
Здесь же я приведу исходный код процедур из своего кода.
Чтение содержимого карты
Первым делом нам необходимо убедиться в наличии карты и возможности считать данные с нее. Для этого воспользуемся значениями PICC_IsNewCardPresent() и PICC_ReadCardSerial(), если хотя бы одно из них неопределено – выходим. Если все хорошо выводим на серийный порт содержимое карты по ее UID.
Хочу отметить, что считывание данных с карты и вывод их на экран займет несколько секунд, поэтому при тестировании не торопитесь убирать карту от считывателя.
Процедура чтения дампа с карты будет иметь следующий вид.

C:


Код:
void
DumpInfo
(
)
{
delay
(
pause
)
;
if
(
!
mfrc522
.
PICC_IsNewCardPresent
(
)
)
{
return
;
}
if
(
!
mfrc522
.
PICC_ReadCardSerial
(
)
)
{
return
;
}
mfrc522
.
PICC_DumpToSerial
(
&
(
mfrc522
.
uid
)
)
;
mfrc522
.
PICC_HaltA
(
)
;
}
Чтение персональной информации
В отличии от чтения дампа карты, при считывании персональной информации нам придется разбирать те данные, которые мы считываем. Под персональной информацией в данном случае мы будем подразумевать имя (First Name) и фамилию (Last Name) владельца карты. Проверив доступность карты по аналогии с предыдущим примером, мы считываем дамп и начинаем его разбирать. Для считывания дампа нам необходимо сначала подобрать ключ для расшифровки данных. В большинстве случаев никто не меняет заводские ключи, поэтому мы используем восемь ключей, указанных в массиве key. Извлеченное First Name и Last Name владельца карты мы поочередно поместим в массивы buffer1 и buffer2, длиной 18 байт.
Кстати, по этим ссылкам можно найти еще много заводских ключей. ikarus23/MifareClassicTool Обратите внимание на последние разделы списка. Интересно, о каких карточках для публичных туалетов идет речь?
https://www.blackhat.com/docs/sp-14...meida-Hacking-MIFARE-Classic-Cards-Slides.pdf.
Вот исходный код процедуры чтения персональной информации владельца карты.

C:


Код:
void
Read_card
(
)
{
delay
(
pause
)
;
// put your main code here, to run repeatedly:
Serial
.
print
(
F
(
"Name: "
)
)
;
byte buffer1
[
18
]
;
MFRC522
::
MIFARE_Key key
;
for
(
byte i
=
0
;
i

#include 
#define RST_PIN         9
// Configurable, see typical pin layout above
#define SS_PIN          10
// Configurable, see typical pin layout above
#define NR_KNOWN_KEYS   8
MFRC522
mfrc522
(
SS_PIN
,
RST_PIN
)
;
// Create MFRC522 instance
// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
byte knownKeys
[
NR_KNOWN_KEYS
]
[
MFRC522
::
MF_KEY_SIZE
]
=
{
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
}
,
// FF FF FF FF FF FF = factory default
{
0xa0
,
0xa1
,
0xa2
,
0xa3
,
0xa4
,
0xa5
}
,
// A0 A1 A2 A3 A4 A5
{
0xb0
,
0xb1
,
0xb2
,
0xb3
,
0xb4
,
0xb5
}
,
// B0 B1 B2 B3 B4 B5
{
0x4d
,
0x3a
,
0x99
,
0xc3
,
0x51
,
0xdd
}
,
// 4D 3A 99 C3 51 DD
{
0x1a
,
0x98
,
0x2c
,
0x7e
,
0x45
,
0x9a
}
,
// 1A 98 2C 7E 45 9A
{
0xd3
,
0xf7
,
0xd3
,
0xf7
,
0xd3
,
0xf7
}
,
// D3 F7 D3 F7 D3 F7
{
0xaa
,
0xbb
,
0xcc
,
0xdd
,
0xee
,
0xff
}
,
// AA BB CC DD EE FF
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
}
// 00 00 00 00 00 00
}
;
char
choice
;
int
pause
;
byte buffer
[
18
]
;
byte block
;
byte waarde
[
64
]
[
16
]
;
MFRC522
::
StatusCode status
;
byte newUid
[
4
]
{
0xDE
,
0xAD
,
0xBE
,
0xFF
}
;
void
setup
(
)
{
// put your setup code here, to run once:
Serial
.
begin
(
9600
)
;
// Initialize serial communications with the PC
while
(
!
Serial
)
;
// Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI
.
begin
(
)
;
// Init SPI bus
mfrc522
.
PCD_Init
(
)
;
// Init MFRC522
Serial
.
println
(
"1. Read dump the card"
)
;
Serial
.
println
(
"2. Read personal data"
)
;
Serial
.
println
(
"3. Write personal data"
)
;
pause
=
2000
;
}
void
loop
(
)
{
// put your main code here, to run repeatedly:
start
(
)
;
}
void
DumpInfo
(
)
{
// put your main code here, to run repeatedly:
delay
(
pause
)
;
if
(
!
mfrc522
.
PICC_IsNewCardPresent
(
)
)
{
return
;
}
if
(
!
mfrc522
.
PICC_ReadCardSerial
(
)
)
{
return
;
}
mfrc522
.
PICC_DumpToSerial
(
&
(
mfrc522
.
uid
)
)
;
mfrc522
.
PICC_HaltA
(
)
;
}
void
Read_card
(
)
{
delay
(
pause
)
;
// put your main code here, to run repeatedly:
Serial
.
print
(
F
(
"Name: "
)
)
;
byte buffer1
[
18
]
;
MFRC522
::
MIFARE_Key key
;
for
(
byte i
=
0
;
i
<
6
;
i
++
)
key
.
keyByte
[
i
]
=
0xFF
;
//some variables we need
byte block
;
byte len
;
MFRC522
::
StatusCode status
;
block
=
4
;
len
=
18
;
// Look for new cards
if
(
!
mfrc522
.
PICC_IsNewCardPresent
(
)
)
{
return
;
}
// Select one of the cards
if
(
!
mfrc522
.
PICC_ReadCardSerial
(
)
)
{
return
;
}
Serial
.
println
(
F
(
"**Card Detected:**"
)
)
;
mfrc522
.
PICC_DumpDetailsToSerial
(
&
(
mfrc522
.
uid
)
)
;
//dump some details about the card
//------------------------------------------- GET FIRST NAME
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
4
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
//line 834 of MFRC522.cpp file
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"Authentication failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
status
=
mfrc522
.
MIFARE_Read
(
block
,
buffer1
,
&
len
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"Reading failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
//PRINT FIRST NAME
for
(
uint8_t i
=
0
;
i
<
16
;
i
++
)
{
if
(
buffer1
[
i
]
!=
32
)
{
Serial
.
write
(
buffer1
[
i
]
)
;
}
}
Serial
.
print
(
" "
)
;
//---------------------------------------- GET LAST NAME
byte buffer2
[
18
]
;
block
=
1
;
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
1
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"Authentication failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
status
=
mfrc522
.
MIFARE_Read
(
block
,
buffer2
,
&
len
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"Reading failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
//PRINT LAST NAME
for
(
uint8_t i
=
0
;
i
<
16
;
i
++
)
{
Serial
.
write
(
buffer2
[
i
]
)
;
}
//----------------------------------------
Serial
.
println
(
F
(
"\n**End Reading**\n"
)
)
;
delay
(
1000
)
;
//change value if you want to read cards faster
mfrc522
.
PICC_HaltA
(
)
;
mfrc522
.
PCD_StopCrypto1
(
)
;
}
void
Write_card
(
)
{
// put your main code here, to run repeatedly:
MFRC522
::
MIFARE_Key key
;
for
(
byte i
=
0
;
i
<
6
;
i
++
)
key
.
keyByte
[
i
]
=
0xFF
;
// Look for new cards
if
(
!
mfrc522
.
PICC_IsNewCardPresent
(
)
)
{
return
;
}
// Select one of the cards
if
(
!
mfrc522
.
PICC_ReadCardSerial
(
)
)
{
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
.
print
(
F
(
" PICC type: "
)
)
;
// Dump PICC type
MFRC522
::
PICC_Type piccType
=
mfrc522
.
PICC_GetType
(
mfrc522
.
uid
.
sak
)
;
Serial
.
println
(
mfrc522
.
PICC_GetTypeName
(
piccType
)
)
;
byte buffer
[
34
]
;
byte block
;
MFRC522
::
StatusCode status
;
byte len
;
Serial
.
setTimeout
(
20000L
)
;
// wait until 20 seconds for input from serial
// Ask personal data: Family name
Serial
.
println
(
F
(
"Type Family name, ending with #"
)
)
;
len
=
Serial
.
readBytesUntil
(
'#'
,
(
char
*
)
buffer
,
30
)
;
// read family name from serial
for
(
byte i
=
len
;
i
<
30
;
i
++
)
buffer
[
i
]
=
' '
;
// pad with spaces
block
=
1
;
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
block
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"PCD_Authenticate() failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
else
Serial
.
println
(
F
(
"PCD_Authenticate() success: "
)
)
;
// Write block
status
=
mfrc522
.
MIFARE_Write
(
block
,
buffer
,
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: "
)
)
;
block
=
2
;
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
block
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"PCD_Authenticate() failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
// Write block
status
=
mfrc522
.
MIFARE_Write
(
block
,
&
buffer
[
16
]
,
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: "
)
)
;
// Ask personal data: First name
Serial
.
println
(
F
(
"Type First name, ending with #"
)
)
;
len
=
Serial
.
readBytesUntil
(
'#'
,
(
char
*
)
buffer
,
20
)
;
// read first name from serial
for
(
byte i
=
len
;
i
<
20
;
i
++
)
buffer
[
i
]
=
' '
;
// pad with spaces
block
=
4
;
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
block
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"PCD_Authenticate() failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
// Write block
status
=
mfrc522
.
MIFARE_Write
(
block
,
buffer
,
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: "
)
)
;
block
=
5
;
status
=
mfrc522
.
PCD_Authenticate
(
MFRC522
::
PICC_CMD_MF_AUTH_KEY_A
,
block
,
&
key
,
&
(
mfrc522
.
uid
)
)
;
if
(
status
!=
MFRC522
::
STATUS_OK
)
{
Serial
.
print
(
F
(
"PCD_Authenticate() failed: "
)
)
;
Serial
.
println
(
mfrc522
.
GetStatusCodeName
(
status
)
)
;
return
;
}
// Write block
status
=
mfrc522
.
MIFARE_Write
(
block
,
&
buffer
[
16
]
,
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: "
)
)
;
Serial
.
println
(
" "
)
;
mfrc522
.
PICC_HaltA
(
)
;
// Halt PICC
mfrc522
.
PCD_StopCrypto1
(
)
;
// Stop encryption on PCD
}
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
)
;
}
}
void
dump_byte_array1
(
byte
*
buffer
,
byte bufferSize
)
{
for
(
byte i
=
0
;
i
<
bufferSize
;
i
++
)
{
Serial
.
print
(
buffer
[
i
]
<
0x10
?
" 0"
:
" "
)
;
Serial
.
write
(
buffer
[
i
]
)
;
}
}
void
start
(
)
{
choice
=
Serial
.
read
(
)
;
if
(
choice
==
'1'
)
{
Serial
.
println
(
"Read dump the card"
)
;
DumpInfo
(
)
;
}
else
if
(
choice
==
'2'
)
{
Serial
.
println
(
"Read personal data"
)
;
Read_card
(
)
;
}
else
if
(
choice
==
'3'
)
{
Serial
.
println
(
"Write personal data"
)
;
Write_card
(
)
;
}
}
Проверка результатов
Для записи прошивки откроем среду разработки Arduino IDE, подключим макетную плату Arduino. Выберем соответствующие модели платы и порт (одна из самых частых ошибок новичков) это неправильный порт подключения. Нажмем кнопку со стрелкой. В случае успешной записи на плату мы увидим в нижней части экрана соответствующее сообщение Done uploading. В случае ошибки подробности будут выведены красным цветом.
После успешной компиляции необходимо припаять модуль MFRC к плате, по схеме указанной ранее. Можно припаять и до записи, главное отключить от компьютера на время пайки. Далее можно сразу подключить устройство к смартфону с помощью переходника, а можно воспользоваться терминалом в Arduino IDE. В своих примерах далее я приведу скриншоты с телефона. На телефон должен быть установлен Serial клиент, например Serial USB Terminal. Открываем клиента, указываем порт и подключаемся. Если все прошло успешно, мы увидим следующую картинку.

В качестве первого примера рассмотрим карту на один проезд на метро (использованную).
Для транспортных карт используются только секторы 0 и 15 карты. Нулевой сектор - специальный и в его нулевом блоке хранится уникальный идентификатор карты, который используется для того, чтобы отличать ее от других. В 15, сохраняется специфичная для метрополитена информация. Нажимаем 1 и подносим карту к считывателю. Иногда данные считываются не сразу, придется поводить карточкой несколько раз. В итоге получаем следующий дамп.



Так как карта уже давно использовалась скрывать какие-либо данные с нее нет смысла.
Для сравнения, карта для прохода ребенка в школу содержит (точнее может содержать) явно больше данных.



Теперь попробуем прочитать и записать персональную информацию на нашу карту.
Процесс считывания довольно прост – нажимаем 2 и подносим карту. В моем примере в обоих полях указано античат .



Процесс записи немного сложнее: нам надо успеть ввести имя за указанный интервал времени, иначе мы получим ошибку.



Проверить успешность записи можно снова нажав 2 и убедившись в том, что записанная ранее информация сохранилась на карте.

Что в итоге
В итоге мы получили портативное устройство, позволяющее считывать и записывать данные на бесконтактную карту. В силу ряда соображений я не стал касаться темы смены UID. Желающие могут самостоятельно изучить примеры, поставляемые вместе с библиотекой MFRC522. Замечу лишь, что бесконтактная карта, идущая вместе с считывателем, не позволяет перезаписывать идентификаторы UID. Для того, чтобы их перезаписывать, необходимо приобрести специальные, перезаписываемые карты, на известной китайской площадке. Для того, чтобы убедиться, что продаваемая карта действительно является перезаписываемой, нужно посмотреть на отзывы. Если продавец обманывает, покупатели обязательно напишут, обратное тоже верно.
В остальном, устройство может быть использовано например для бэкапа содержимого бесконтактных карт.
 
Ответить с цитированием

  #2  
Старый 19.02.2020, 03:11
larchik
Новичок
Регистрация: 07.06.2019
Сообщений: 0
С нами: 3650634

Репутация: 0
По умолчанию

Отличная статья!
 
Ответить с цитированием

  #3  
Старый 18.05.2021, 11:29
Евгений Л
Новичок
Регистрация: 28.12.2019
Сообщений: 0
С нами: 3357143

Репутация: 0
По умолчанию

По идее если еще на Soft serial повесить блю туз модуль,то можно сделать девайс автономным.Или как вариант использовать esp32 ,тогда можно и по зубу и по вафле конектить.
 
Ответить с цитированием
Ответ



Предыдущая тема Следующая тема

Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.