Можно ли использовать указатели функций для запуска «данных»? - PullRequest
0 голосов
/ 19 июня 2010

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

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

Ответы [ 4 ]

9 голосов
/ 19 июня 2010

Теоретически вы можете, согласно Карлу Норуму.Это называется «самоизменяющийся код».

На практике вас обычно останавливает операционная система.Большинство основных современных операционных систем предназначены для проведения различий между «читаемой», «читаемой» и «исполняемой» памятью.Когда ядро ​​ОС такого типа загружает программу, оно помещает код на специальную «исполняемую» страницу, которая помечена только для чтения, чтобы пользовательское приложение не могло ее изменить;в то же время попытка получить адрес, которого нет на «исполняемой» странице, также вызовет исключение ошибки.Это делается в целях безопасности, потому что многие виды вредоносных программ, вирусов и других хаков зависят от того, как программа переходит в измененную память.Например, хакер может передать данные приложения, которые заставляют какую-то функцию записать вредоносный код в стек, а затем запустить его.

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

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

6 голосов
/ 19 июня 2010

Да, вы можете сделать это абсолютно.Вас ничто не остановит, если ваша система или компилятор не будут этому как-то мешать (как, например, у вас есть гарвардская архитектура).Просто убедитесь, что ваши «данные» являются действительными инструкциями, прежде чем прыгать, или вы рискуете катастрофой.

1 голос
/ 19 июня 2010

Невозможно даже попытаться сделать что-то подобное легально на языке Си, поскольку нет законного способа сделать указатель на функцию, указывающую на «данные».Указатели на функции на языке C могут быть инициализированы / назначены только из других указателей на функции, даже если вы используете явное преобразование.Если вы нарушаете это правило, поведение не определено.

Также возможно инициализировать указатель функции из целого числа (с помощью явного преобразования) с результатами, определенными реализацией (в отличие от неопределенных результатов в других случаях).).Однако попытка выполнить «данные» путем выполнения вызова через указатель, полученный таким образом, все еще приводит к неопределенному поведению.

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

0 голосов
/ 19 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...