C: приведение указателей на функции для редактирования исполняемого кода - PullRequest
0 голосов
/ 26 февраля 2019

Предположим, следующий код:

int f1(int x, int y);

int main(void) {
    printf("%d", f1(2,3));
    char* x = (char*)&f1;
    //edit the stuff here?
    printf("%d", f1(2,3));
    return 0;
}

int f1(int x, int y){
    return x*y;
}

Теперь, несмотря на то, что это действительно глупо, и вы никогда бы не практически сделали бы это, как бы вы поступили?Если бы я хотел, чтобы эта функция добавила два числа вместо вычитания или даже пошла на что-то более сложное, какие шаги я должен предпринять?Как выяснить, какой правильный машинный код нужен для получения желаемого результата?

1 Ответ

0 голосов
/ 26 февраля 2019

Хотя это не невозможно, это обычно нецелесообразно, поскольку существуют значительные препятствия, в том числе:

  • Память, содержащая машинные инструкции, обычно помечается как недоступная для записи, поэтому необходимо изменить параметры защитыпрежде чем это может быть изменено.(В системах Unix посмотрите mprotect.)
  • Изменения, которые необходимо внести, зависят от архитектуры - каждая архитектура процессора имеет свои собственные инструкции и свои собственные кодировки этих инструкций.Вы должны выяснить, какие новые инструкции нужно написать и как их кодировать.
  • Широко доступно программное обеспечение для кодирования инструкций, а именно ассемблер.Чтобы на лету превратить инструкции в кодировки, можно встроить ассемблер в программу или вызвать другой в другом процессе.Тогда возникает проблема, как извлечь инструкции из вывода ассемблера (объектный файл).Ассемблер также можно использовать обычным способом для подготовки заданной последовательности команд, а не на лету в работающей программе.
  • Инструкции сразу после того, как они были закодированы ассемблером, обычно представлены в промежуточной формегде ссылки на определенные места в памяти являются символическими или относятся к определенным контрольным точкам.Прежде чем поместить их в работающую программу, эти ссылки должны быть преобразованы в фактические адреса в программе.
  • Как только вы знаете, какие инструкции вы хотите заменить в функции, возникает проблема, заключающаяся в том, что они могут быть больше, чеминструкции подлежат замене, поэтому они не подойдут.Затем вам потребуется обходной путь, такой как поиск альтернативного места для ваших инструкций и, вместо того, чтобы вставлять ваши инструкции в функцию, вставлять небольшую инструкцию, которая переходит к вашим инструкциям.Обратите внимание, что память, которую вы используете для своих инструкций, должна быть помечена как исполняемая.
  • После изменения основной памяти в кеше команд может храниться старая копия инструкций, поэтому вам необходимо очистить кэш инструкций.

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

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