Способы защиты микроконтроллеров

Если вы изучали микроконтроллеры, вы, вероятно, слышали о битах конфигурации. Для разных семейств они называются по-разному: в AVR это предохранители, а в PIC — слово конфигурации. Сегодня мы углубимся в них и рассмотрим их применение для защиты прошивки в контроллере. И покажем как обходить такую ​​защиту. Погнали!

AVR

  В семействе AVR для регулировки используются предохранители. Предохранители (от англ. Fuse — предохранитель) — это особые биты в микроконтроллере, которые, как и все биты, хранят информацию. Его основные особенности заключаются в следующем:

  • они хра­нят­ся и про­шива­ются отдель­но от осталь­ной памяти;
  • из­меня­ются толь­ко извне;
  • уп­равля­ют работой мик­рокон­трол­лера на самом низ­ком уров­не.

Луч­ше все­го их мож­но объ­яснить на при­мере дозимет­ра РКСБ-104.

                                                До­зиметр РКСБ-104

  Его базовая настройка осуществляется одним переключателем на передней панели. Но для более точных настроек снятие защитной крышки с задней стенки и использование небольших переключателей (белые в центре).

                                        Зад­няя панель со сня­той крыш­кой

  В AVR эти биты для удобства объединены в байты: старший, младший, защитный и дополнительный. Доступен каждый битовый байт → бит. Младший байт обычно отвечает за часы, а старший байт — за плюшки. Биты различаются от чипа к чипу, поэтому в идеале каждый чип следует рассматривать отдельно с использованием документации.

  Значение битов этого семейства инвертировано: 1 означает, что бит был очищен, а 0 означает, что он установлен. Но программы для прошивки МК работают по разному. Для разных программ необходимо уточнить логику работы с предохранителями.

Что могут фьюзы в этом семей­стве МК:

  • уп­равле­ние так­тирова­нием (час­тота генера­тора, внеш­ний или внут­ренний генера­тор);
  • раз­решение на чте­ние про­шив­ки мик­рокон­трол­лера (самое инте­рес­ное, но об этом поз­же);
  • уп­равле­ние тай­мерами;
  • за­щита EEPROM;
  • бо­лее спе­цифич­ные фун­кции, их надо уточ­нять к кон­крет­ному чипу.

Са­мые «популяр­ные» биты:

  • CKSEL — их четыре, и они отве­чают за так­тирова­ние;
  • SUT — их два, и они управля­ют режимом запус­ка так­тирова­ния;
  • CKOPT — кон­фигури­рует внут­ренний генера­тор;
  • RSTDISBL — режим работы нож­ки RESET МК;
  • SPIEN — раз­решение SPI;
  • EESAVE — защита EEPROM;
  • BOOTRST — адрес, отку­да начать исполнять код;
  • BODEN — кон­троль питания;
  • SELFPRGEN — раз­решение записи в память изнутри;
  • OCDEN — вот он, бит, раз­реша­ющий чте­ние про­шив­ки.

  Счи­тыва­ют фьюзы обыч­но не вруч­ную, а с помощью спе­циаль­ных каль­кулято­ров. Вот один из них — Fusecalc.

 Софт

                                        warning

    При работе с фьюза­ми будь пре­дель­но вни­мате­лен. Неп­равиль­но выс­тавлен­ный бит может прев­ратить чип в «кир­пич». Перед про­шив­кой уточ­няй логику работы с фьюза­ми в тво­ей прог­рамме.

Linux

    Я обыч­но работал с прог­раммой avrdude. При­веду пару команд без допол­нитель­ных парамет­ров (чип, прог­рамма­тор). Счи­тыва­ние про­шив­ки из чипа в файл:

      $ avrdude -U flash:r:flash_dump.hex:i

 

Счи­тыва­ние энер­гонеза­виси­мой памяти в файл:

      $ avrdude -U eeprom:r:eeprom_dump.raw:r
 

За­пись про­шив­ки из фай­ла в чип:

        $ avrdude -U flash:w:flash_dump.hex
 

За­пись энер­гонеза­виси­мой памяти из фай­ла:

         $ avrdude -U eeprom:w:eeprom_dump.raw
 

За­пись фьюзов (0xc3 -> lfuse; 0x99 -> hfuse):

        $ avrdude -U lfuse:w:0xc3:m -U hfuse:w:0x99:m
 

Чте­ние фьюзов в фай­лы:

          $ avrdude -U hfuse:r:hfuse.txt:h -U lfuse:r:lfuse.txt:h
 

Есть допол­нитель­ные парамет­ры и -p. Пер­вый отве­чает за прог­рамма­тор, а вто­рой — за чип. В качес­тве при­мера — коман­да для про­шив­ки кон­трол­лера ATmega328p с помощью USBASP:

           $ avrdude -U flash:w:flash_dump.hex -c usbasp -p m328p
 

В коман­дах есть стран­ные стро­ки вида flash:w:flash_dump.hex. Это стро­ки в спе­циаль­ном фор­мате для avrdude. Для чего такое решение — не знаю ни я, ни кто‑либо еще.

Час­ти этих строк раз­делены дво­ето­чиями:

  • пер­вая часть — область памяти в МК (нап­ример flash или lfuse);
  • вто­рая — нап­равле­ние (w — write или r — read);
  • третья — файл на локаль­ном устрой­стве (нап­ример файл с про­шив­кой);
  • пос­ледняя (опци­ональ­ная) — фор­мат фай­ла (нап­ример r — raw или i — ihex, инте­лов­ский шес­тнад­цатерич­ный).

Бо­лее спе­цифич­ные слу­чаи при­мене­ния этой стро­ки выходят за рам­ки дан­ной статьи.

Windows

Окон­щики обыч­но поль­зуют­ся прог­рамма­ми с GUI. Нап­ример, AVRdude GUI.

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

  Вто­рая вклад­ка кон­фигури­рует прог­рамма­тор: какая исполь­зует­ся модель и на каком пор­те она сидит.

  Вклад­ка управле­ния защит­ными битами.

  А вот наконец и фьюзы. Зада­ются они как бай­ты.

Как видишь, все прос­то, и исполь­зовать фьюзы мож­но, даже не откры­вая тер­минал!

                                       info

   На Arduino мож­но кон­фигури­ровать МК, не задумы­ваясь о работе фьюзов. Этим занима­ется Arduino IDE в авто­мати­чес­ком режиме.

STM

  Семейство STM использует биты в специальных регистрах для конфигурации. Информацию об этих регистрах и их назначении ищите в документации. Можно и необходимо изменять значения этих регистров на лету, но, в отличие от AVR, здесь настраивается не только самый низкий уровень (например, часы), но и небольшие периферийные устройства.

  Нас­тра­ивать надо мно­го, даже если про­ект в духе Hello world, поэто­му обыч­но это дела­ется не руч­ной записью регис­тров, а с помощью кра­сиво­го и мощ­ного соф­та.

Софт

   STM32CubeMX — это офи­циаль­ное и бес­плат­ное прог­рам­мное обес­печение, соз­данное в ком­пании STMicroelectronics. У нее есть и дру­гая и тоже бес­плат­ная IDE для сво­их МК — Atollic TrueSTUDIO. Но нач­нем мы с «Кубика».

 

                                                          CubeMX

   Разобраться с этим просто: вы создаете проект, выбираете контроллер — и вперед. Порты настраиваются прямо на интерактивном изображении, а периферийные устройства — в меню слева. Большинство опций подписаны: вам больше не нужно заходить в таблицу и разбираться с битами регистра. И в конце, нажав соответствующую кнопку, программа сгенерирует код на языке программирования в виде подключаемого файла.

   Atollic TrueSTUDIO — это еще одна наворо­чен­ная IDE для мик­рокон­трол­леров STM. В ней мож­но и код писать, и отла­живать. А еще она хорошо сты­кует­ся с «Кубом».

                          www

Есть еще System Workbench for STM32 и, конеч­но, Arduino IDE с ее неис­числи­мыми модуля­ми.

Посторонним вход запрещен!

   Ес­ли ты не хочешь исполь­зовать софт про­изво­дите­ля МК, мож­но все сде­лать руками. Бла­го это отно­ситель­но нет­рудно. При­веду при­мер кода из одно­го сво­его про­екта.

void init_uart()

{
UART1_CR2 |= UART_CR2_TEN; // Transmitter enable
UART1_CR2 |= UART_CR2_REN;
UART1_CR2 |= UART_CR2_RIEN;
UART1_CR3 &= ~(UART_CR3_STOP1 | UART_CR3_STOP2);
UART1_BRR2 = (F_CPU/UART_BAUD) & 0x000F;
UART1_BRR2 |= (F_CPU/UART_BAUD) >> 12;
UART1_BRR1 = ((F_CPU/UART_BAUD) >> 4) & 0x00FF;
}
  Эта функция отвечает за настройку UART. Как видите, без кубиков можно обойтись (хотя на самом деле CubeMX на моем ноутбуке просто не установился из-за слабых возможностей).

Библиотеки

  Прошивки STM обычно пишутся с использованием специальных библиотек. Есть как официальные, так и кастомные (HAL и SPL). Проще говоря, это стандартный набор библиотек. Можно, конечно, и без них — мне даже больше нравится: ты лучше понимаешь, как работает твой код.

При­веду коман­ды для ком­пиляции и про­шив­ки STM8 из упо­мяну­того про­екта.

    $ sdcc --Werror --std-sdcc99 -mstm8 -DSTM8S103 -lstm8 -mstm8 --out-fmt-ihx ../devctrl.c
    $ stm8flash -c stlinkv2 -p stm8s103f3 -w devctrl.ihx
 
 

Здесь мы видим две прог­раммы — stm8flash для про­шив­ки и sdcc для ком­пиляции. Может, кому‑то при­годит­ся.

  • stm8flash — это прог­рамма c GitHub. По наз­начению — тот же AVRdude, толь­ко для STM8. Я исполь­зовал три аргу­мен­та: для ука­зания прог­рамма­тора, в моем слу­чае st-linkv2 (прог­рамма­тор ST-Link, под­робнее — в моей прош­лой статье), -p для ука­зания целево­го чипа (у меня это была плат­ка с AliExpess с чипом STM8S103F3); -w для нап­равле­ния работы (write, записать) и файл с про­шив­кой.
  • sdcc (small device C compiler) — ком­пилятор язы­ка C для «малень­ких» устрой­ств, то есть для мик­рокон­трол­леров. Это ана­лог GCC, но для МК.
  • —Werror — счи­тать все пре­дуп­режде­ния ошиб­ками. Стран­но, навер­ное, ведь обыч­но прог­раммис­ты забива­ют на пре­дуп­режде­ния, а тут такое. Еще есть --std-sdcc99 — это стан­дарт язы­ка. Я исполь­зовал этот, потому что он оши­бок не выдавал.

                                   warning

  В низкоуровневом программировании стандарты языка C очень важны, и код хорошо компилируется по одному стандарту и либо не компилируется вообще, либо не будет работать должным образом в соответствии с другим стандартом. Чтобы ответить на этот вопрос, начните с руководств, которые научили вас программировать. Обычно во введении указывается, какой стандарт будет включен в книгу.

  Ос­таль­ные аргу­мен­ты, кро­ме фай­ла кода, — это для какого МК ком­пилиро­вать код.

PIC

  Здесь вместо предохранителей используется специальное конфигурационное слово из двух байтов. У этого слова есть адрес в памяти, который необходимо объяснить в документации. Там же вы можете найти структуру слова и назначение битов. Кстати, логика битов в этом семействе неоднозначная. Вы можете иметь в виду как «включено», так и «выключено». Пожалуйста, внимательно прочтите документацию.

  При­веду вырез­ку из до­кумен­тации на чип PIC16F627A.

                                                    Вы­рез­ка из докумен­тации

Тут мы видим сле­дующие нас­трой­ки:

  • CP — защита flash-памяти, то есть про­шив­ки;
  • CPD — защита области с дан­ными;
  • LVP — низ­коволь­тная про­шив­ка;
  • и так далее.

  Слово конфигурации функционирует как статическая глобальная переменная на языке C. Существует фрагмент кода, который, когда он мигает, записывается непосредственно в область памяти, отвечающую за настройку микроконтроллера. Очевидно, вы не можете изменить это на ходу. Работа аналогична контроллерам AVR.

Софт

  Здесь покажем лишь особенности при кон­фигури­рова­нии этих самых кон­трол­леров.

  Тут исполь­зует­ся язык ассем­бле­ра, и мы видим строч­ку __CONFIG 03FF4H. Воз­можно, это мак­рос или что‑то подоб­ное, но нам важен смысл — это чис­ло записы­вает­ся как кон­фигура­цион­ное сло­во и кодиру­ет в себе нас­трой­ки МК, в ком­мента­риях к коду они даже под­писаны.

И вот еще один при­мер кода. Он уже из статьи на «Хаб­ре» (кста­ти, нас­тоятель­но рекомен­дую с ней озна­комить­ся).

This program assumes a 20 MHz resonator or crystal

-- is connected to pins OSC1 and OSC2.
pragma target clock 20_000_000 -- oscillator frequency
-- configuration memory settings (fuses)
pragma target OSC HS -- HS crystal or resonator
pragma target WDT disabled -- no watchdog
pragma target LVP disabled -- no Low Voltage Programming
pragma target MCLR external -- reset externally         

   Он написан на язы­ке JAL, который был соз­дан спе­циаль­но для прог­рамми­рова­ния это­го семей­ства МК. Этот код явно читабель­нее ассем­бле­ра. Чего уж говорить — поч­ти все читабель­нее ассем­бле­ра! Хотя PIC тра­дици­онно прог­рамми­руют­ся имен­но на нем.

                                  www

                 IDE для PIC MPLAB и JAL.

Защита и взлом

  Мы проанализировали теорию. Теперь поговорим о защите. Как вы понимаете, в семействе AVR бит предохранителя служит защитой. Если защита установлена, контроллер не позволит вам загрузить программное обеспечение. А если сбросить биты защиты, возможно ли это? Возможно, но даже здесь вас поджидает поросенок: при сбросе бита защиты МК очистит всю память.
Ну из-за софта не вышло — пройдемся по железу. Электроника не программирование — есть что потрогать. Итак, перейдем к истории: раньше были микросхемы памяти с УФ-стиранием.

                          Чип M27c256B — память с УФ‑сти­рани­ем

  На корпусе чипа было специальное окошко, которое обычно чем-то заклеивалось. Вы записываете данные при программировании встроенными средствами, а стираете их с помощью специального устройства, похожего по конструкции на лампу для ногтей.
Лампа-коготь

 

                                                 Лам­па для когот­ков

  Открываешь окно, вставляешь микросхему в устройство — и через некоторое время забираешь чистую микросхему. С лампой все понятно — можно одолжить у жены. Главное — не замечать, иначе не объяснишь, что нужна лампа для стирания памяти через окошко.

А вот с окош­ком что делать? На сов­ремен­ных чипах его нет. Если дыр­ки нет — надо ее сде­лать! Я знаю три метода: механи­чес­кий, химичес­кий и лазер­ный.

  1. При механи­чес­ком методе, как выразил­ся поль­ский бло­гер, szlifierka precyzyjna — пре­цизи­онной шлиф­машин­кой, то есть дре­мелем, надо твер­дос­плав­ной насад­кой прог­рызть дыроч­ку в кор­пусе.
  2. При химичес­ком методе при­меня­ется смесь кис­лот (цар­ская вод­ка, если я не оши­баюсь), и ей прот­равли­вает­ся все то же отвер­стие. Но раз­добыть азот­ную кис­лоту проб­лематич­но: ее обо­рот под кон­тро­лем, пос­коль­ку она исполь­зует­ся при про­изводс­тве взры­воопас­ных веществ, так что при­дет­ся поис­кать дру­гой спо­соб. Если, конеч­но, у тебя не заваля­лась баноч­ка азот­ной кис­лоты.
  3. Пос­ледний метод исполь­зует лазер. Им прос­то про­жига­ется окош­ко. Лазер мож­но най­ти на ЧПУ‑гра­верах, но хва­тит ли их мощ­ности — я не знаю.

  Ко­роче, будем счи­тать, что окош­ко к под­ложке чипа ты про­делал.

                                    По­лучит­ся что‑то похожее

  Далее нужно понять, где та область, которую нужно защитить, а где — стереть. По сути, нам нужно облучить все, кроме Flash и EEPROM. Определять где что, придется интуитивно. Можно смотреть каналы Lisin YT и CuriousMarc — есть вскрытие и изучение фишек. Вы можете посмотреть типичные ошибки и технологию вскрытия фишек.
Итак, что защищать, мы придумали, и затем защищаем чем-то светорезистивным. Например, святая синяя изолента. Ну а после вставляем фишку в ластик и немного ждем.

                                           info

Ес­ли что, про лам­пу для ног­тей — это шут­ка. Нуж­на лам­па с опре­делен­ной дли­ной вол­ны и мощ­ностью.

Все, исхо­да два: либо все сде­лано пра­виль­но и акку­рат­но и защита сня­та, либо что‑то пош­ло не так и тебе при­дет­ся искать, что имен­но.

PIC и STM

  PIC такие же, как AVR. Условия такие же, метод тот же.
С STM все несколько интереснее. Способы защиты описаны в документации. Короче говоря, они не запрещают считывать чип, и создают условия, чтобы это было невозможно.

  Но, собирая информа­цию для этой статьи, я нат­кнул­ся на стра­ницу с инте­рес­ным наз­вани­ем — «Счи­тыва­ние защищен­ной про­шив­ки из флеш‑памяти STM32F1xx с исполь­зовани­ем ChipWhisperer». Смысл это­го метода в прог­рам­мной ата­ке на про­шив­ку. Этот метод бли­же к темати­ке жур­нала.

Вместо напутствия

  Прежде чем я побегу украсть программное обеспечение, имейте в виду: даже если вы загрузите его, оно будет в виде двоичного кода, который все равно нужно проанализировать, изучить и восстановить логику работы, настолько это сложно. Так что, на мой взгляд, проще взломать компьютер программиста, написавшего прошивку, и скачать ее исходный код. Но это не тема моей статьи!

Click to rate this post!
[Total: 0 Average: 0]

Leave a reply:

Your email address will not be published.