C код, который проверяет сам себя *в ОЗУ*

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

код сначала компилируется на кросс-платформе разработки, генерируя .выход elf. Утилита используется для удаления двоичного изображения, и это изображение сжигается для вспышки на целевой платформе вместе с размером изображения. Когда цель запускается, она копирует двоичный файл в правильную область ОЗУ и переходит к ней. Программа также вычисляет контрольную сумму всех слова в эльфе, которые предназначены для рама,и это тоже выжжено во вспышке. Таким образом, мой образ теоретически мог бы проверить свой собственный резидентный образ ram, используя a-priori начальный адрес и размер, сохраненный во flash, и сравнить с суммой, сохраненной во flash.

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

я устранил изменения из-за переменных, определенных моим приложением, переместив процедуру контрольной суммы впереди всех других инициализаций в приложении (что имеет смысл b/c, зачем запускать любой из них, если проверка целостности не удается, верно?), но убийца-это само время выполнения C. Похоже, что есть некоторые элементы, относящиеся к malloc и литье указателя и другие вещи, которые изменяются до main() - это даже вошло.

Is вся идея самоконтроля C-кода хромает? Если бы был способ заставить app и CRT .данные в разных разделах я мог бы избежать трэша CRT, но можно утверждать, что если цель состоит в том, чтобы проверить целостность изображения перед его выполнением (большая часть), то инициализированные данные CRT должны быть частью этого. Есть ли способ сделать контрольную сумму кода в ОЗУ, как это вообще?

FWIW, я, кажется, застрял с требованием для этого. Лично я бы подумал, что путь - это контрольная сумма двоичный флеш, перед передачей в ОЗУ, и доверяйте загрузчику и ОЗУ. Паранойя должна где-то закончиться, верно?

разное детали: цепочка инструментов GNU, изображение содержит .text, .rodata и .data как один непрерывно загружается кусок. Нет ОС, это голый металл, встроенный. Основной загрузчик существенно memcpyмой двоичный файл в ОЗУ, по заданному адресу. Нет перемещения происходят. VM не используется. Контрольная сумма требует тестирования только один раз в init только.


обновлено Нашел это, сделав это..

__attribute__((constructor)) void sumItUp(void) {
    // sum it up
    // leave result where it can be found
}

.. что я могу получить сумму до того, как почти все, кроме инициализации malloc/sbrk vars от CRT init, а некоторые vars принадлежат "нечистым".O" и "язык.о." Теперь malloc/sbrk значение-это то, что я знаю из сценария компоновщика проекта. Если нечистые.o и locale.o может быть смягчен, может быть в бизнесе.

обновление С Я могу контролировать точку входа (по тому, что указано в flash для основного загрузчика), кажется, что лучший угол атаки теперь-использовать кусок пользовательского кода ассемблера для настройки указателей стека и sdata, вызвать процедуру контрольной суммы, а затем разветвиться на "нормальный" _start-код.

5 ответов


Если контрольная сумма сделана достаточно рано, вы можете использовать только переменные стека, а не записывать в какие-либо переменные раздела данных, то есть сделать все, что вам нужно для выполнения контрольной суммы [и всех предыдущих шагов, чтобы добраться до этой точки], используйте только локальные переменные для хранения вещей в [вы можете читать глобальные данные, конечно].

Я довольно убежден, что правильный способ-доверять flash & loader для загрузки того, что находится во вспышке. Если вы хотите проверить код, конечно, идите и сделайте это [предполагая, что он, конечно, не изменяется загрузчиком - например, загрузка общих библиотек во время выполнения или перемещение самого исполняемого файла, например, случайных виртуальных адресных пространств и т. д.]. Но на данные, загруженные из flash, нельзя полагаться после правильного запуска выполнения.

Если есть требование от кого-то другого, что вы должны это сделать, то, пожалуйста, объясните им, что это невозможно реализовать, и что "требование, как оно стоит", "сломано".


Я бы предложил подойти к этому как к исполняемому пакеру, например UPX по.

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

  • Я бы не доверял загрузчику или чему-либо в flash, что не было навязано мне.
  • в сети плавает исходный код, который использовался для защиты одного из, Я думаю, последних телефонов HTCs. Посмотрите вокруг на forum.xda-developers.com и посмотрите, сможете ли вы найти его и использовать для примера.
  • Я бы оттолкнулся от этого требования. Производители мобильных телефонов тратят много времени на блокировку своих изображений, и в конечном итоге все они избиты. Это похоже на порочный круг.

можете ли вы использовать сценарий компоновщика для размещения нечистых.o и locale.o до или после всего остального, позволяя вам проверять все, кроме тех и вещей malloc/sbrk? Я предполагаю, что malloc и sbrk вызываются в загрузчике, который загружает ваше приложение, поэтому трэш, вызванный ими, не может быть устранен?

Это не ответ, чтобы просто сказать вам, чтобы бороться с этим требованием, но я согласен, что это кажется чрезмерным. Я уверен, что вы не можете вдаваться в детали, но Я предполагаю, что авторы спецификаций обеспокоены злонамеренными пользователями / хакерами, а не обычным повреждением памяти из-за космических лучей и т. д. В этом случае, если злонамеренный пользователь / хакер может изменить то, что загружено в ОЗУ, они могут просто изменить вашу процедуру проверки (которая сама работает из ОЗУ, правильно?) всегда вернуть счастливое состояние, как бы хорошо ни суммы рутинную они не больше предназначен.

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


В общем, то, что вы хотите сделать, невозможно, так как на многих (большинство?) платформы загрузчик программы может "переместить" некоторые константы адреса программы.


можете ли вы обновить загрузчик для выполнения теста контрольной суммы на двоичном образе Flash resident, прежде чем он будет скопирован в ОЗУ?