2015-09-06 2 views
4

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

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

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

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

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

+0

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

+0

@Wimmel, вы думаете, что компиляторы не оптимизируются между вызовами? Ха-ха. – rightfold

+0

@elyse, и если функция находится в отдельной единице компиляции? Или линкер также может оптимизировать это? – wimh

ответ

7

Возможно, вы можете объявить строковый литерал как const volatile, например.

const volatile char myliteral[] = "some literal string"; 

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

Наконец, если строка и ее хэш находятся в двух разных единицах перевода (например, в file1.c и file2.c), вам нужна оптимизация времени ссылки, чтобы сделать inlining в время сборки. С текущим GCC (т.е. GCC 4.9 или 5) Вы должны явно проходом -flto во время компиляции и во время компоновки, чтобы получить оптимизацию канального времени, так что если вы не сделаете явно, что (например, с CC=gcc -flto -O2 в ваших Makefile), этого не произойдет.

Кстати, вы можете проверять весь исполняемый файл или всю общую библиотеку или некоторый заданный объектный файл. Подробности - специфичные для ОС. В Linux см dlopen(3), dlsym(3), dladdr(3), dl_iterate_phdr(5), elf(5), proc(5)

Кроме того, вы могли бы хэширования некоторые случайный суффикс подстроки от начальной буквальным (например, хэш myliteral+random()%strlen(myliteral) во время выполнения) и сохранить и сравнить с постоянным набором таких частичные хеши. Компилятор вряд ли вложит все это!

Я действительно считаю, что это не настоящая проблема на практике: никто не заботится о вашем исполняемом файле, и никто не тратит время на его декомпиляцию.

+1

Близко связанный, вы можете применить результат вызова функции контрольной суммы к 'volatile void', чтобы убедиться, что он не оптимизирован. 'static_cast (check_checksum (literal, hash)); вы также можете вычислить хеш с помощью функций constexpr, если вы находитесь в C++ 11 –

+0

любые ресурсы/инструменты, которые знаете, где я могу узнать, как контрольная сумма целиком исполняемая или разделяемая библиотека для окон? – Thomas

+0

Я никогда не использовал Windows, но (по крайней мере, в Linux) во время сборки [GCC] (http://gcc.gnu.org/) вычисляет свою собственную контрольную сумму, поэтому вы можете заглянуть в ее «Makefile'-s –

Смежные вопросы