Если после прочтения статьи про чтение кода ключа-таблетки iButton, Вам в голову пришла мысль, что можно сделать и обратную комбинацию – значит мы мыслим в одинаковом направлении :)
Сразу хочу сказать, что эта идея далеко не новая, и воспользовавшись поиском можно найти различные решения – примеры можно найти в конце статьи в ссылках.
Итак, что же нам нужно?
А нужно нам всего-навсего произвести симуляцию 1-Ware slave-устройства, выдавая себя за iButton :)
Для этого нужно вспомнить, что происходит в линии 1-Wire:
Сначала происходит
1. инициализация – ведущее устройство (домофон) подаёт импульс RESET, после него ведомое устройство (это мы) должно дать ответ PRESENCE (прижать линию к земле на 60 — 240 микросекунд)
Далее происходит сам обмен информации:
2. домофон выдает команду на чтение ПЗУ (ROM) – это должно быть 33h.
Информация, как мы помним, передаётся побайтно, бит за битом.
При этом «0» передаётся прижиманием линии к земле в течении всего тайм-слота (60 — 120 микросекунд)
А «1» передаётся кратковременным прижиманием (на 1-15микросекунд) и последующим отпусканием линии.
3. домофон выдерживает некоторое время и начинает посылать импульсы приема информации.
Т.к. в ответ ожидается 8 байт информации – будет 64 импульса (по одному импульсу для передачи каждого бита информации от нас).
Если мы хотим передать «0» — мы удерживаем линию на логическом нуле, а если хотим передать «1», то можем ничего не делать :)
Эмулируя ключ, мы должны сначала передать номер серии устройства 01h.
Затем собственно 6 байт номера ключа (начиная с младшего байта) и в самом конце – байт CRC-кода предыдущей информации.
Для ключа, рассмотренного в статье про iButton – это будет последовательность байт:
01h
41h
CEh
67h
0Fh
00h
00h
B6h
Попробуем это дело запрограммировать :)
Чтобы не бегать постоянно к домофону – начальную проверку можно попробовать сделать в протеусе :)
Поместим в проект две ардуины – в одну загрузим скетч работы с iButton, а во вторую будем грузить код нашего эмулятора :)
Кроме того, при симуляции схемы можно воспользоваться виртуальным инструментарием. Например, подключив в Протеусе на линию 1-Wire виртуальный осциллограф – можно вживую понаблюдать – как происходит обмен информацией :)
блок-схема скетча для эмуляции iButton будет такой
А если мы не знаем ключ – сможем ли мы его подобрать перебором?
Оценочно прикинем – сколько времени понадобится на подбор ключа :)
У моего ключа-таблетки номер
00000F67CE41
, что даёт нам возможность предположить, что пока для нумерации iButton-ов используются первые 4 байта номера :)
Вне всяких сомнений — это меньше 281 биллиона, которые можно спрятать в шести байтах :)
И даёт нам всего 4 миллиарда вариантов :)
0xFFFFFFFF = 4294967295
Прикинем — сколько времени займёт проверка одного ключа:
PRESENCE ~ 480 мкс
8 бит команды 120 мкс * 8
64 бита данных 120 мкс *64
Итого ~ 10 мс => 100 ключей в секунду (в датащите упоминается про 75 ключей в секунду)
Получается, что на полный перебор потребуется 497 дней :( Что-то долго :)
В интернете упоминается, что такой брутфорс (brute force) на домофонах не сработает и после трёх неправильных ключей домофон загудит и впадёт в ступор на 5 минут :)
Однако выход есть – дело в том, что на некоторых моделях домофонов в новой чистой памяти домофона (предназначенной для хранения ключей жильцов) все биты установлены в 1 (т.е. забиты FF-ами).
И если ключ будет выдавать тоже единицы, то программа подумает, что в чистой памяти тоже хранятся коды ключей и они совпадают с тем, что записано в нашем универсальном ключе и дверь откроется :)))
Это действительно дыра в программном обеспечении контроллера и есть во всех дешёвых контроллерах. Причём простая до смеху. Контроллер проверяет ключ (причём обычно только последнии 4 байта — контроллер то дешёвый) с записаными в ЭСПЗУ. А как выглядят пустые ячейки? То есть если записать ключ вида FFFFFF......FFFFFF что будет? Правильно, он уже везде прописан :) Подверженны все домофоны типа Цифрал ТС, Визит, Метаком
А где же скетч эмулятора?
Ниже приводится набросок такого скетча – вам остаётся только освежить в памяти – что происходит на линии 1-Wire и наполнить кодом функции:
void wire_send_byte(byte dsbyte)
byte wire_read_byte()
void wire_write0(void)
void wire_write1(void)
или же полностью переписать скетч самостоятельно ;)
Набросок скетча (ВНИМАНИЕ – СКЕТЧ НЕ ДОПИСАН ДО КОНЦА):
/*
* Эмулируем работу ключа-таблетки iButton типа DS1990A */ int onepinio = 10; // порт для подключения 1-Wire // данные ключа - номер серии, 6 байт номера, байт CRC byte key_data[8] = {0x1, 0x41, 0xCE, 0x67, 0x0F, 0x00, 0x00, 0xB6}; void setup() { Serial.begin(9600); } void loop() { // считываем импульс RESET из линии // wire_read_RESET(); // // выдаём в линию импульс PRESENCE // wire_PRESENCE(); // // считываем команду от домофона // int b = wire_read_byte(); // // что за команду считали? :) // if(b==0xF0) // SEARCH ROM { // // начинаем двубитную передачу :( // wire_send_duos_bits(); } else { if(b==0x33) // READ ROM { // // отправляем данные iButton :) // wire_send_data(); } } delay(300); } // // ждём пока линия не прижмётся к земле // void wire_wait() { pinMode(onepinio, INPUT); while(digitalRead(onepinio)) { delayMicroseconds(1); } } // // двубитное общение с ведущим устройством - см. AN187 // void wire_send_duos_bits() { } // // считываем импульс RESET из линии // void wire_read_RESET() { pinMode(onepinio, INPUT); while(digitalRead(onepinio)) { delayMicroseconds(1); } while(!digitalRead(onepinio)) { delayMicroseconds(1); } } // // выдаём в линию 1-Wire сигнал PRESENCE // для этого нужно прижать линию к земле на 60-240 микросекунд, а затем отпустить // void wire_PRESENCE() { pinMode(onepinio, OUTPUT); digitalWrite(onepinio,LOW); // прижимаем линию к земле delayMicroseconds(120); // 60-240 микросекунд pinMode(onepinio, INPUT); // отключаемся delayMicroseconds(450); } // // выдача в линию данных iButton // void wire_send_data() { for(int i=0;i<8;i++) wire_send_byte(key_data[i]); } // // выдача в линию байта данных // void wire_send_byte(byte dsbyte) { } // // считываем байт данных из линии // byte wire_read_byte() { } // // пишем бит "0" в линию // void wire_write0(void) { } // // пишем бит "1" в линию // void wire_write1(void) { }
О спасибо, это то что я давно искал.
ОтветитьУдалитьСам придумал?
ОтветитьУдалитьдавно хотел узнать, как это всё работает.
ОтветитьУдалитьЖдите, скоро будут еще статьи по схожих темах.
ОтветитьУдалитьЖдем:)
ОтветитьУдалитьинтересная статья, спасибо)
ОтветитьУдалитьОжидаю новых статей!
ОтветитьУдалитьгодная статья. спасибо, пригодится.
ОтветитьУдалитьЯ обычно с кулака открываю, если чо.
ОтветитьУдалитьСлишком сложно, попроще никак?
ОтветитьУдалить2Magnolia-Fan: чтоб попроще получилось, придется растянуть на десяток статей :-(
ОтветитьУдалитьИнтересно.
ОтветитьУдалитьСложно:(
ОтветитьУдалить