Я пытаюсь получить изображение-резидентный экземпляр для самой контрольной суммы, что проще сказать, чем сделать.
Код сначала компилируется на платформу кросс-разработки, генерируя вывод .elf. Утилита используется для выделения бинарного изображения, и это изображение сжигается для мигания на целевой платформе вместе с размером изображения. Когда цель запущена, она копирует двоичный файл в правильную область ram и переходит к нему. Утилита также вычисляет контрольную сумму всех слов в эльфе, которые предназначены для бара, и это тоже сожжено во вспышке. Таким образом, мое изображение теоретически могло бы проверять собственное резидентное изображение с использованием априорного начального адреса и размера, сохраненного во флэш-памяти, и сравнить с суммой, сохраненной во флэш-памяти.
Это теория в любом случае. Проблема в том, что как только изображение начинает выполняться, в разделе .data
происходит изменение в изменении переменных. К тому времени, когда сумма будет выполнена, изображение, которое было суммировано, больше не является изображением, для которого утилита рассчитала сумму.
Я исключил изменения из-за переменных, определенных моим приложением, переместив процедуру контрольной суммы перед всеми другими инициализациями в приложении (что имеет смысл b/c, зачем запускать ее, если проверка целостности завершается неудачно?), но убийца - это время выполнения C. Похоже, что есть некоторые элементы, относящиеся к malloc
и литье указателей и другие вещи, которые были изменены до того, как main()
будет даже введен.
Является ли вся идея самоконтроля C-кода хромой? Если бы был способ принудительно использовать приложения и CRT.data в разных разделах, я мог бы избежать трэша CRT, но можно утверждать, что если цель заключается в проверке целостности изображения перед его выполнением (большей частью), то эти инициализированные данные ЭЛТ должны быть частью этого. Есть ли способ самостоятельно сделать контрольную сумму кода в ОЗУ?
FWIW, я, похоже, придерживался требования для этого. Лично я бы подумал, что путь - это проверять двоичную информацию во флэш-памяти, до передачи на плунжер, и доверять загрузчику и барану. Паранойя должна заканчиваться где-то вправо?
Дополнительная информация: цепочка инструментов - это GNU, изображение содержит .text
, .rodata
и .data
как один загружаемый фрагмент. Нет ОС, это встроенный металл. Первичный загрузчик, по существу, memcpy
мой двоичный код в баран на заданном адресе. Никаких переездов не происходит. VM не используется. Контрольная сумма нуждается только в тестировании только в init.
обновляется Найдено, что, делая это.
__attribute__((constructor)) void sumItUp(void) {
// sum it up
// leave result where it can be found
}
.., что я могу получить сумму, сделанную до почти всего, кроме инициализации vars malloc
/sbrk
с помощью CRT init и некоторых vars, принадлежащих "impure.o" и "locale.o". Теперь значение malloc
/sbrk
- это то, что я знаю из компоновщика проекта script. Если impure.o и locale.o могут быть смягчены, может быть в бизнесе.
Обновление Поскольку я могу контролировать точку входа (по тому, что указано во флэш-памяти для первичного загрузчика), кажется, лучшим углом атаки теперь является использование части пользовательского кода ассемблера для настройки указателей стека и sdata, вызова подпрограммы контрольной суммы и затем перейдите в "обычный" код _start.