Изменяется ли адрес функции за время выполнения
Я пишу что-то на C++, где я хочу прочитать текст из файла, который указывает на корреляции между строками и функциями, которые я объявил в своей программе. Например, файл может читать:
sin:sin
PI:getPi
+:add
Я хотел, чтобы код взял это и создал хеш-таблицу или вектор структур данных String и Function Pointer. К сожалению, я понимаю, что код не сможет найти имя функции во время выполнения, поэтому я хочу иметь возможность поместить адреса этих функций в файл. Но эта система, конечно, не будет работать, если адреса функций будут отличаться при каждом запуске или компиляции программы. Просвещение или альтернативное решение любой из этих проблем было бы здорово.
3 ответа
Может быть?
Ваша система использует ASLR?
Рандомизация расположения пространства адресов, это метод, используемый современными системами для предотвращения выполнения частными или привилегированными функциями атак ROP.
В основном это рандомизирует расположение функций в памяти. Это можно победить, если вы знаете расположение базового изображения, потому что все по-прежнему относительно. Вы часто будете видеть нотацию, например, 0xDEADBEEF+13.
Смотрите ASLR для получения дополнительной информации.
Вы можете безопасно брать адреса функций (указатели функций) во время компиляции. Задачей загрузчиков изображений является перемещение адресов ваших функций при запуске вашей программы. Вам не нужно беспокоиться об изменении адресов функций.
Конечно, вы не должны печатать адрес функции на стандартный вывод и помещать этот адрес как числовое значение в вашу программу. Это пострадает от проблемы, которую вы описываете.
Получить адрес функции C++ sin()
просто используйте &sin
в вашем коде.
Чтобы получить адрес функции C++ по строке, вам нужно иметь такой код:
if (function_name == "sin") return &sin;
else if (function_name == "add") return &add;
else ...
или подходящая структура данных с парами указателей строк / функций.
Дело в том, что: не храните числовые адреса функций в файле. Возьмите и используйте адреса функций в вашей программе напрямую. Числовой адрес функции не должен иметь никакого значения для вашей программы.
Нельзя полагаться на то, что адреса остаются неизменными, поскольку ОС может использовать рандомизацию размещения адресного пространства для снижения эффективности эксплойтов.
Вы можете полагаться на относительные адреса функций, если они все находятся в одном и том же связанном двоичном файле. Выберите один, чтобы быть основой, и вычтите это из всех других.
Естественно, все это будет отключено, если вы перекомпилируете и / или перекомпоновали Я бы попробовал найти другой метод.
Одним из таких методов будет использование целочисленных индексов для каждой функции и ведение таблицы того, какой индекс соответствует какой функции. Это вводит другой слой косвенности, но был бы намного более устойчивым.
Редактировать: Если вы не хотите создавать статическую таблицу, вы можете позволить коду создать ее при инициализации программы, используя статические объекты и конструкторы.
struct FunctionTable
{
typedef std::unordered_map<std::string, void *> table;
static table& get()
{
static table the_table;
return the_table;
}
FunctionTable(std::string name, void * func)
{
get().insert(name, func);
}
};
double getPi()
{
return 3.14159;
}
static FunctionTable ft_getPi = FunctionTable("getPi", getPi);