Простой способ склонировать Keeloq брелок
Идеи о том как обходить неклонируемость брелков с rolling codes
Введение
На пред-пандемийном DIY meetup от mail_ru был доклад о том как “клонировать” брелок с динамическим кодом Keeloq.
Собственно, что сделали ребята: ретранслятор по мобильному интернету с блекджеком и ардуиной динамического кода с единственного источника - имеющегося брелока Keeloq:
Оригинальный брелок -> хост-сервер -> приложение на мобильном -> передатчик-ретранслятор с блютуз
О том как более изящно можно решить задачу
Забиваем гвозди микроскопом
Пишем брутфорсилку Keeloq:
- на OpenCL для GPU-фермы
- на верилоге для FPGA-фермы
На выходе получаем ключ, зашитый в оригинальный брелок + значение 16 битного счётчика (не так важно, может пересинхронизироваться). Ключ затем зашиваем в необходимое число болванок брелоков.
Умный в гору не пойдёт..
..умный гору обойдёт.
Для начала посмотрим что же собой представляет динамический код по стандарту Keeloq:
Sync Counter - тут ключевой элемент. Это 16 битный счётчик, который на передающей стороне каждый раз инкрементируется на единицу, а перед передачей шифруется секретным ключом. Вся задача: уметь послать такое значение, которое на приёмной стороне при дешифровке секретным ключом будет располагаться “близко” к текущему (запомненому в приемнике) значению счётчика (блок сравнения под цифрой 4 на рисунке выше).
Немного о том как работает блок сравнения: от последнего принятого и корректно дешифрованного блока запоминается текущее (принятое) значение счётчика (обозначим как k), с этого момента приёмник ожидает в принятом сигнале декодировать значение счётчика в диапазоне k+1…k+16 - т.о. существует некое защитное окно в 16 значений: например брелок случайно нажался будучу в кармане, либо при использовании брелока безошибочный прием был невозможен (помеха, большое расстояние). В случае декодирования в ожидаемом диапазоне приемник запоминает новое (принятое и декодированное) значение счётчика.
В случае выхода за границы k+16 процедура немного усложняется: необходимо двойное нажатие кнопки брелока, чтобы механизм приёмника убедился в отсутствии replay-атаки, успехом будет считаться декодирование двух последовательных значений счётчика n и n+1 (AFAIK, в диапазоне до k+32768), только после этого новое значение счётчика пропишется в приёмнике
Собственно идея
Берём донора (оригинальный брелок) и считываем с него (для примера) 10000 посылок, после чего эти посылки раскладываем на “кучки” по числу требуемых брелков-клонов (допустим 4). Т.о. в первой кучке у нас будут посылки: 1, 5, 9, 13..; во второй: 2, 6, 10, 14.. и т.д. Т.о. в каждой кучке 2500 посылок оригинального брелка. Далее заливаем эти кучки-дампы в I2C EEPROM и используем уже с внутренним счётчиком вместо оригинальной микросхемы HCS200. Т.о. эти брелки с дампами, заполненными по round robin будут самосинхронизирующейся системой: если будет декодировано значение счётчика меньше чем текущее k, приёмник просто проигнорирует посылку как повреждённую/неверную, если будет принято значение в диапазоне k+1…k+16, то оно перезапишет текущее значение счётчика.
Да, само собой будут возникать ситуации, когда в зависимости от сценариев использования будет происходить рассинхронизация брелков, но в этом нет ничего страшного, просто понадобится дополнительный раз (или несколько) нажать на кнопку. Также брелки-клоны вообще можно сделать вечными сняв “весь круг” значений счётчика (65536), каждый брелок-клон будет хранить 16384 значений (не проблема для I2C EEPROM) и “закольцовывать” свой внутренний 14-битный счётчик адреса ячейки.
В общем и целом, это по сути доведенная до ума изначальная идея, с заменой онлайн-ретранслятора на оффлайн-“реплики” и выпиливанием всей серверной инфраструктуры. Для пользователя это максимально близко к изначальному кейсу использования брелока.