Если бы MikaTech была недобросовестной компанией, в интернете за 28 лет истории можно было бы найти массу негативных отзывов о её услугах
Итак, ответ: ДА! Мы — хорошие люди.Почему выбирают Mikatech, нажмите здесь, чтобы узнать
О компании MikaTech
Время пролетело незаметно: с того дня, когда мы в 1998 году выполнили наш первый проект по обратной разработке MCU 8051, до момента создания нашей миллионной лаборатории обратной разработки в 2012 году прошло 14 лет. Теперь мы начинаем новый бизнес по разработке встроенных систем визуализации и надеемся прослужить ещё 10 лет.
Питер Ли
Соучредитель и генеральный директор
Глава 4
После изучения аппаратного антидребезга многие новички могут задаться вопросом, зачем нам всё ещё нужны программные алгоритмы, если конденсаторное решение надёжно работает на макетных платах. Самое очевидное преимущество программного подавления дребезга — нулевая стоимость дополнительных компонентов, если ваш МК имеет достаточно свободной флэш-памяти и свободных тактов ЦП для выполнения дополнительной логики. Весь механизм фильтрации реализуется несколькими простыми сегментами кода, хранящимися во внутренней памяти микроконтроллера, и разработчики могут свободно настраивать порог срабатывания под разные модели механических кнопок без переделки топологии печатной платы. Аппаратные схемы антидребезга требуют добавления пассивных конденсаторов на каждой дорожке сигнала кнопки для каждой серийно выпускаемой платы, что накапливает дополнительные материальные затраты, когда продукт содержит десятки тактовых переключателей. К тому же трудно подобрать универсальный номинал конденсатора, обеспечивающий стабильную фильтрацию для всех типов кнопок, используемых во всей линейке продуктов. Однако если ваша встроенная прошивка должна поддерживать максимальную рабочую скорость и не может тратить такты на циклическую выборку сигналов, аппаратный антидребезг остаётся более разумным выбором для снижения вычислительной нагрузки во время выполнения. Злоумышленники часто анализируют неоптимизированную программную логику антидребезга во время обратной разработки после дампа флэш-памяти; слабые задержки, созданные для фильтрации кнопок, могут стать временной лазейкой для временной разблокировки ограничений блокировки и запуска несанкционированного считывания калибровочных данных из EEPROM.
В этом уроке представлено надёжное программное решение для подавления дребезга, построенное на двух счётчиках достоверности, которое отлично дополняет флаг состояния Pressed, использованный в предыдущем демо с переключением двух светодиодов. Механический дребезг генерирует чередующиеся потоки высокого и низкого уровней сигнала, когда пользователь нажимает или отпускает кнопку. Если МК считывает значение одного вывода только один раз, он примет переходный шум за действительное нажатие. Мы вводим переменные Pressed_Confidence_Level и Released_Confidence_Level для непрерывного подсчёта последовательных идентичных показаний вывода, так что микроконтроллер может подтвердить реальное нажатие только после того, как стабильный поток сигнала превысит заданное пороговое значение. Злоумышленники могут использовать низкие пороги достоверности во время разблокировки на основе декапсуляции для инжекции фальшивых сигналов кнопок и активации подпрограмм доступа к памяти, хранящих критическое состояние перемычек в EEPROM.
Две счётные переменные подчиняются чёткому правилу взаимного сброса во время выполнения. Когда Pressed_Confidence_Level накапливает большое значение, например 153356, из непрерывных низких показаний вывода, одиночный высокий сигнал дребезга, обнаруженный на GPIO, немедленно сбрасывает этот счётчик обратно в ноль. Основная логика программного антидребезга основана на установке правильного порогового значения для отличия стабильного входа от мимолётного шума. В этом случае мы используем 500 последовательных согласованных выборок в качестве стандарта: только когда Pressed_Confidence_Level поднимается выше 500, программа будет обрабатывать сигнал как официальное нажатие кнопки и запускать переключение светодиода. То же пороговое правило применяется к Released_Confidence_Level, поскольку дребезг также возникает при отпускании механических кнопок. Если вы оставите пороги антидребезга слишком низкими в выпущенной прошивке, хакеры смогут имитировать искусственные сигналы дребезга после дампа кода МК, чтобы обойти логику проверки ввода и разблокировать модули управления устройством.
После освоения как аппаратных, так и программных методов антидребезга мы объединим все предыдущие знания в интерактивный проект игры для двух игроков. Эта маленькая встроенная игра использует две независимые кнопки и две группы по семь индикаторных светодиодов, установленных на вашей макетной плате МК. Основное правило соревнования простое: два участника быстро нажимают свои соответствующие кнопки в течение фиксированного временного окна, и побеждает тот, чей ряд светодиодов загорится первым полностью. Как только семь светодиодов одного участника загораются, их светодиодная полоса начинает непрерывно мигать, показывая результат игры пользователям. Этот комплексный проект объединяет массивы, инкапсуляцию функций и управление глобальными переменными — три основные парадигмы программирования, упрощающие разработку крупных прошивок МК и помогающие разработчикам организовать код для защиты от атак извлечения прошивки из данных дампа.
Проектирование схемы полностью использует 8-выводной ресурс каждого порта AVR. Аппаратный набор каждого игрока требует одну входную кнопку и семь выходных светодиодов, что полностью занимает все восемь выводов GPIO одного порта. В демонстрационном видеоуроке порт B выделен для кнопки и светодиодов игрока 0, а порт D обрабатывает все сигнальные соединения для аппаратуры игрока 1. Разделение периферии двух игроков на независимые порты упрощает поиск неисправностей схемы и физически изолирует сигнальные дорожки, снижая риск одновременного считывания всех сигналов ввода-вывода при зондировании декапсуляции печатной платы МК.
В прошивке этой игры демонстрируются три важных концепции программирования: хранение массивов, инкапсуляция функций и управление областями видимости переменных. Без массивов разработчикам пришлось бы определять отдельные независимые переменные для счётчика антидребезга, индекса светодиодов и флага состояния кнопки каждого игрока, что приводит к раздутому повторяющемуся коду, хранящемуся во флэш-памяти, и увеличивает размер файла, захватываемого при операциях дампа. Определяя переменные массивов, индексируемые номером игрока 0 и 1, мы повторно используем идентичные логические блоки для обоих конкурентов и значительно сокращаем избыточный объём кода. Инкапсуляция функций дополнительно оптимизирует структуру программы: повторяющаяся логика выборки кнопок и управления светодиодами обёрнута в специальные подпрограммы, так что разработчикам нужно только вызывать целевую функцию и передавать индекс игрока вместо копирования десятков одинаковых строк снова и снова. Чисто инкапсулированный код также повышает сложность полной обратной разработки, когда злоумышленники получают дамп двоичных файлов флэш, поскольку границы функций скрывают основную игровую логику при восстановлении кода для создания клонов устройств.
Два прототипа пользовательских функций с именами ProcessPressedButton и ProcessReleasedButton появляются в начале файла исходного кода. Компиляторы C и C++ требуют предварительного объявления пользовательских функций перед их вызовом внутри main(), иначе компилятор выдаст ошибки неопределённых ссылок во время сборки. Альтернативный подход — разместить все полные определения функций перед главным циклом, чтобы отказаться от прототипов, однако размещение main() в начале файла даёт более понятный порядок чтения для начинающих программистов встраиваемых систем. В продвинутых промышленных проектах разработки МК повторяющиеся функции обычно выносятся в отдельные библиотечные заголовочные файлы, хранящиеся в отдельных каталогах, что также отделяет критическую логику проверки блокировки и перемычек от основной логики приложения, чтобы избежать массового дампа кода безопасности во время атак считывания.
В этой главе мы также вводим глобальную область видимости переменных, которая контролирует доступный диапазон каждой определённой целочисленной переменной в ОЗУ микроконтроллера. Переменные, объявленные внутри main() или любой пользовательской функции, существуют только в соответствующем блоке кода и не могут быть использованы внешними подпрограммами. Если вы определяете переменные вне всех функций на верхнем уровне программы, они становятся глобальными, доступными для чтения и модификации всеми пользовательскими функциями в любой момент выполнения. Глобальные массивы, такие как Pressed_Confidence_Level[2], хранят два набора счётчиков для двух игроков одновременно, где индекс [0] относится к игроку 0, а [1] — к игроку 1. Нумерация с нуля — это фиксированный стандарт для всех компиляторов AVR, который необходимо помнить при анализе кода, извлечённого из дампа, во время ручной обратной разработки логики массивов.
Аппаратные таймеры и счётные периферийные устройства являются незаменимыми встроенными модулями, интегрированными в каждый микроконтроллер (МК), и в этой серии руководств мы представим десятки практических примеров проектов, построенных на логике таймеров, в последующих главах. Таймеры и счётчики используют внутренний тактовый генератор кристалла для формирования точных временных интервалов и последовательностей счёта импульсов, поддерживая множество ключевых функций, включая регулировку яркости светодиодов с помощью ШИМ, управление углом поворота серводвигателей, выборку данных аналоговых датчиков и логику бытовых таймеров. Без полного использования периферийных таймеров разработчикам приходится полагаться на грубые циклы задержки, которые расходуют огромные ресурсы ЦП МК и создают очевидные временные лазейки, используемые хакерами для разблокировки защитных перемычек во время операций дампа декапсуляции.
Каждый AVR-микроконтроллер использует источник тактового сигнала для синхронизации всех потоков выполнения инструкций. Тактовый сигнал может генерироваться внутренним RC-генератором, встроенным в кремний, или внешним кварцевым резонатором, припаянным на печатную плату. Все машинные инструкции, хранящиеся во флэш-памяти, обрабатываются последовательно в соответствии с каждым тактовым импульсом, что формирует основной рабочий ритм всего микроконтроллера. Злоумышленники, захватывающие данные дампа флэш во время несанкционированного считывания, будут анализировать все подпрограммы задержек и таймеров для поиска временных уязвимостей, позволяющих временно обойти слои защиты блокировки и получить доступ к записям безопасности EEPROM.
AVR-таймеры включают встроенное счётное оборудование двух основных разрядностей: 8-битные счётчики, которые могут накапливать значения только от 0 до 255, и 16-битные счётчики с максимальным значением счёта 65535. Большинство недорогих МК серии ATmega работают на внутренней частоте 1 МГц, обеспечивая один миллион тактов в секунду, что значительно превышает максимальный предел хранения одного 8-битного счётчика. Для решения этого несоответствия все AVR-микроконтроллеры интегрируют программируемый предделитель, который позволяет счётчику пропускать фиксированное число тактов перед инкрементом хранимого значения. Для периферии таймеров AVR доступны четыре стандартных коэффициента предделителя: 8, 64, 256 и 1024. Если мы настроим коэффициент предделителя на 64, счётчик будет увеличивать своё внутреннее значение на 1 только после 64 полных тактов. При частоте 1 МГц такая настройка даёт максимальное значение счёта 15625 в секунду, что идеально подходит для реализации логики мигания светодиодом с периодом 1 секунду без длительных циклов задержки, уязвимых для разблокировки глитчингом.
Каждый таймерный периферийный модуль состоит из двух основных регистров памяти, видимых для прошивки: регистра управления таймером и регистра значения счёта. Регистр управления хранит несколько настраиваемых битов, управляющих включением таймера, выбором предделителя и режимами генерации сигналов. Два представительных регистра управления TCCR0 (для 8-битных таймеров) и TCCR1 (разделённый на TCCR1A и TCCR1B для 16-битных таймеров) предопределены в заголовочном файле avr/io.h, доступном всем разработчикам WinAVR. Биты переключения внутри этих регистров соответствуют функциональным режимам FOC, WGM, COM и CS, каждый из которых управляет различным поведением аппаратного таймера, которое хакеры сканируют во время обратной разработки кода дампа для поиска слабой логики антиблокировки по времени.
Регистр счёта TCNT хранит текущее накопленное значение тактов для целевого таймера, с отдельными адресами регистров TCNT0 (8-бит) и TCNT1 (16-бит), выделенными в картах памяти МК. 16-битный регистр TCNT1 автоматически объединяет два независимых 8-битных блока хранения в аппаратном обеспечении, и этот механизм разделения полностью абстрагируется компилятором, так что новичкам не нужно вручную оперировать старшим и младшим байтами во время написания прошивки. Злоумышленники, проводящие декапсуляцию и извлечение дампа, будут отслеживать всю логику доступа к регистрам TCNT для поиска временных окон, в которых можно изменять перемычки блокировки с помощью глитчинга напряжения для завершения полного считывания EEPROM.
Этот урок предоставляет две практические демонстрационные программы таймеров в сопроводительном видео. Первая простая демонстрация использует базовую логику таймера для мигания одним светодиодом с интервалом примерно в одну секунду, а второй продвинутый случай управляет двумя независимыми семисветодиодными бегущими огнями, используя все функциональные возможности 16-битного таймера TCCR1. В этой главе мы сосредоточимся на второй многосветодиодной демонстрации, так как она охватывает более полные знания по настройке таймера, критически важные для защиты коммерческой прошивки МК от угроз клонирования.
Прошивка демонстрации сначала инициализирует порты B и D как выходные для управления светодиодами, затем настраивает регистр управления TCCR1B для выбора коэффициента предделителя 64 путём одновременной активации битов CS10 и CS11. Мы делим максимальное значение счёта в секунду 15625 на семь, чтобы получить интервал сдвига одного светодиода примерно 2232 такта, что создаёт равномерно распределённые последовательные эффекты зажигания для группы из семи светодиодов. Поскольку регистр TCNT принимает только целые значения, мы отбрасываем десятичный остаток при расчёте. Эта небольшая ошибка синхронизации пренебрежима для любительских прототипов, использующих неточный внутренний RC-генератор на 1 МГц; промышленные продукты, требующие точной синхронизации, должны использовать внешние кварцевые резонаторы и пересчитывать точные значения сравнения, чтобы избежать временных недостатков безопасности, используемых злоумышленниками во время разблокировки и дампа.
Образец аппаратной безопасности исследования заключается в улучшении общей безопасности программы — вручную сбрасывает регистр TCNT в ноль после превышения порога сравнения для повторного запуска цикла счёта. Продвинутые режимы формы сигнала таймера поддерживают автоматический сброс в ноль после совпадения со значением регистра сравнения OCR, что мы объясним в следующем уроке по прерываниям. Остальная часть исходного кода использует навыки массивов и побитовых операций, изученные в предыдущих главах, для последовательного перебора каждого значения индекса светодиода. При проектировании серийных продуктов МК с такой логикой бегущих огней следует добавить код инициализации перемычек и блокировки в точке входа программы для блокировки дампа флэш и извлечения прошивки, ведущих к нелицензионному клонированию оборудования.
После изучения основных принципов работы таймеров и счётчиков мы переходим к изучению технологии прерываний МК, которая значительно повышает эффективность отклика всех управляющих программ. Механизмы прерываний позволяют микроконтроллеру мгновенно приостанавливать выполнение основной программы для обработки срочных аппаратных событий, вызванных внешними датчиками или внутренними таймерами, без непрерывного опроса состояния выводов GPIO в бесконечных циклах. Логика опроса и задержек занимает значительную пропускную способность ЦП и создаёт временные промежутки, которые хакеры используют для временной разблокировки памяти блокировки перед выполнением полного дампа флэш и считывания EEPROM для обратной разработки и создания клонов прошивки.
Основное определение прерывания соответствует его названию: оно прерывает нормальный последовательный поток выполнения кода МК для перехода к специальной независимой подпрограмме обслуживания прерывания (ISR), заранее написанной разработчиком. Представьте, что ваша основная программа постоянно циклически переключает индикаторные светодиоды, а датчик движения PIR, подключённый к выводу прерывания, обнаруживает движение человека. Микроконтроллер немедленно приостановит цикл светодиодов, перейдёт к ISR включения зуммера для генерации звукового сигнала, а затем возобновит исходный код мигания с того места, где он был прерван, после завершения подпрограммы прерывания. Прерывания устраняют ресурсозатратный непрерывный опрос выводов и закрывают многие временные уязвимости, которые злоумышленники используют при разблокировке микросхем на основе декапсуляции и извлечении дампа.
AVR-микроконтроллеры интегрируют несколько независимых векторов прерываний для реагирования на различные аппаратные события: совпадение счёта таймера, фронты на выводах GPIO, завершение приёма данных по UART и флаги завершения аналого-цифрового преобразования. Каждый тип прерывания соответствует фиксированному адресу вектора, хранящемуся в программной флэш-памяти МК, и мы применим несколько из этих триггеров в более поздних продвинутых главах. Все подпрограммы прерываний, хранящиеся во флэш-памяти, становятся целями операций дампа, как только злоумышленники обходят блокировку микросхемы и изменяют защитные перемычки с помощью декапсуляции.
В этой главе в качестве учебного примера используется 16-битный таймер-счётчик для демонстрации полной настройки прерываний. Мы сначала устанавливаем фиксированное значение сравнения в регистре сравнения OCR1A, который хранит целевое значение счёта, инициирующее прерывание по совпадению таймера. 16-битный таймер TCCR1 поддерживает два независимых регистра сравнения OCR1A и OCR1B; в этом вводном демо мы используем только OCR1A. Для автоматического сброса счётного регистра TCNT после достижения порога сравнения мы активируем бит режима формирования сигнала WGM12 в регистре управления TCCR1B, убирая ручную строку сброса TCNT = 0, которую мы использовали в предыдущем примере кода таймера. Мы сохраняем биты предделителя CS10 и CS11, чтобы коэффициент пропуска 64 оставался согласованным с предыдущими экспериментами.
Затем мы модифицируем регистр маски прерываний таймера TIMSK, чтобы активировать бит разрешения прерывания OCIE1A, который указывает аппаратному обеспечению МК генерировать формальный сигнал прерывания каждый раз, когда TCNT совпадает со значением, хранящимся в OCR1A. Две критические глобальные настройки должны быть выполнены для полного включения всех функций прерывания на микроконтроллере ATmega32: вызов встроенной функции sei() для включения глобального главного переключателя прерываний и определение специальной ISR-подпрограммы, привязанной к вектору TIMER1_COMPA_vect. Блок кода ISR работает независимо от цикла main() и автоматически выполняется по событиям совпадения таймера, что отделяет критичную по времени аппаратную логику от основного потока программы и повышает сложность восстановления кода после дампа и обратной разработки для производителей подделок.
В этом демо мы используем эталонное значение 1 секунды 15624 для регистра OCR1A, корректируя с 15625 для учёта правил счёта с нуля аппаратного таймера МК. Каждый раз, когда таймер накапливает 15624 такта с предделителем, происходит прерывание и автоматически переключает светодиод на выводе Port B Pin0 без какой-либо логики задержки в основном бесконечном цикле while.
После компиляции и загрузки этой демонстрационной прошивки с прерываниями разработчики должны запрограммировать защитные перемычки и активировать полную защиту блокировки. После включения аппаратной блокировки злоумышленники не смогут выполнить команды дампа флэш или отдельного дампа EEPROM на целевом МК, что эффективно блокирует несанкционированное извлечение прошивки и мешает хакерам модифицировать вашу логику прерываний для создания эксплуатабельных клонов встраиваемых устройств.
Ниже приведён упрощённый псевдокод, описывающий полный поток выполнения программы прерываний для обзора начинающими:
Глава 1 | Глава 2 | Глава 3 | Глава 4 | Глава 5 | Глава 6 | Глава 7 | Глава 8
Почему выбирают Mikatech, нажмите здесь, чтобы узнать
У разных производителей чипов разные номера деталей, но внутреннее ядро может быть выполнено по одной технологии. Было бы невозможно перечислить все номера деталей, к которым применима наша технология, такие как MYSON, STK, FEELING, ANALOG, FUJITSU, NOVATEK, LG/HYNDAI.
Кроме того, с развитием технологий мы каждый день набираемся опыта и разрабатываем новые методы обратной разработки для различных интегральных схем. Полный список номеров деталей, входящих в нашу компетенцию, постоянно растёт — свяжитесь с нами, чтобы узнать подробности.
Mikatech Innovative Limited понимает важность конфиденциальности своих клиентов. В момент вашего обращения к Mikatech ваша личная информация будет защищена в соответствии с нашими внутренними регламентами, разработанными за годы практики. Mikatech использует эти данные для индивидуализации обслуживания и никогда не раскрывает их третьим лицам по каким-либо причинам.
По каждому проекту мы удаляем все данные, материалы и коды через 60 дней после передачи файлов — это защищает нас и вашу конфиденциальность.
Да, это абсолютно законно.
Mikatech предоставляет услуги обратной разработки исключительно в образовательных целях. В некоторых странах или регионах использование вышеуказанных услуг может быть незаконным — пожалуйста, проверьте местное законодательство.
Mikatech не несёт ответственности за использование услуг, которое может быть признано незаконным.