Есть ли умные случаи модификации кода во время выполнения? - PullRequest
119 голосов
/ 04 апреля 2011

Можете ли вы вспомнить какие-либо законные (умные) варианты использования для модификации кода во время выполнения (программа изменяет свой собственный код во время выполнения)?

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

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

Ответы [ 17 ]

117 голосов
/ 04 апреля 2011

Есть много действительных случаев для модификации кода. Генерация кода во время выполнения может быть полезна для:

  • Некоторые виртуальные машины используют JIT-компиляцию для повышения производительности.
  • Генерация специализированных функций на лету уже давно распространена в компьютерной графике. Смотрите, например Роб Пайк и Барт Локанти и Джон Рейзер Компромисс аппаратного программного обеспечения для растровой графики на Blit (1984) или эта публикация (2006) Крисом Латтнером об использовании Apple LLVM для специализации кода во время выполнения в их стеке OpenGL.
  • В некоторых случаях программное обеспечение прибегает к методике, известной как trampoline , которая включает в себя динамическое создание кода в стеке (или другом месте). Примерами являются вложенные функции GCC и сигнальный механизм некоторых Unices.

Иногда код преобразуется в код во время выполнения (это называется динамический двоичный перевод ):

  • Эмуляторы , как у Apple Rosetta , используют эту технику для ускорения эмуляции. Другой пример - программное обеспечение Transmeta для преобразования кода .
  • Сложные отладчики и профилировщики как Valgrind или Пин используют его для инструментов кода во время его исполнения.
  • До того, как были сделаны расширения для набора команд x86, программное обеспечение для виртуализации , такое как VMWare, не могло напрямую запускать привилегированный код x86 внутри виртуальных машин. Вместо этого ему пришлось переводить любые проблемные инструкции на лету в более подходящий пользовательский код.

Модификация кода может использоваться для обхода ограничений набора инструкций:

  • Было время (давно я знаю), когда у компьютеров не было инструкций для возврата из подпрограммы или для косвенного обращения к памяти. Самомодифицирующийся код был единственным способом реализовать подпрограммы, указатели и массивы .

Больше случаев модификации кода:

  • Многие отладчики заменяют инструкции на реализации точек останова .
  • Некоторые динамические линкеры изменяют код во время выполнения. Эта статья предоставляет некоторые сведения о перемещении DLL-библиотек Windows во время выполнения, что фактически является формой модификации кода.
35 голосов
/ 04 апреля 2011

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

23 голосов
/ 04 апреля 2011

Одна действительная причина в том, что в наборе инструкций asm отсутствуют некоторые необходимые инструкции, которые вы могли бы собрать самостоятельно. Пример: на x86 нет способа создать прерывание для переменной в регистре (например, создать прерывание с номером прерывания по оси). Были разрешены только постоянные числа, закодированные в код операции. С помощью самодифицирующегося кода можно эмулировать это поведение.

21 голосов
/ 04 апреля 2011

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

17 голосов
/ 04 апреля 2011

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

17 голосов
/ 04 апреля 2011

Существует много случаев:

  • Вирусы обычно использовали самоизменяющийся код для «деобфускации» своего кода перед выполнением, но этот метод также может быть полезен для предотвращения реверс-инжиниринга, взлома и нежелательных хакерских атак.
  • В некоторых случаях может быть определенная точка во время выполнения (например, сразу после чтения файла конфигурации), когда известно, что - для остальной части времени жизни процесса - определенная ветвь будет всегда или никогдапринять: вместо ненужной проверки какой-либо переменной, чтобы определить, какой способ перехода, сама инструкция перехода может быть изменена соответствующим образом
    • например. Может стать известно, что будет обработан только один из возможных производных типов, так что виртуальныйотправка может быть заменена определенным вызовом
    • Обнаружив, какое оборудование доступно, использование соответствующего кода может быть жестко закодировано
  • Ненужный код можно заменить на no-opинструкции или перепрыгнуть через него, или иметь следующий бкод, сдвинутый непосредственно на место (проще, если используются независимые от позиции операционные коды)
  • Код, написанный для облегчения собственной отладки, может вводить команду прерывания / сигнала / прерывания, ожидаемую отладчиком в стратегическом месте.
  • Некоторые выражения предикатов, основанные на пользовательском вводе, могут быть скомпилированы в собственный код библиотекой
  • Включение некоторых простых операций, которые не видны до времени выполнения (например, из динамически загружаемой библиотеки) ...
  • Условное добавление этапов самоинструмента / профилирования
  • Трещины могут быть реализованы в виде библиотек, которые изменяют код, который их загружает (не «сам», изменяющий в точности, но требующий тех же методов и разрешений).
  • ...

В некоторых моделях безопасности операционных систем самоизменяющийся код не может работать без прав root / admin, что делает его непрактичным для общего назначения.

СВикипедия:

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

В таких операционных системах даже такие программы, как JavaВМ нужны права root / admin для выполнения своего кода JIT.(Подробнее см. http://en.wikipedia.org/wiki/W%5EX)

15 голосов
/ 04 апреля 2011

Synthesis OS в основном частично оценил вашу программу относительно вызовов API и заменил код ОС результатами.Основным преимуществом является то, что многие проверки ошибок исчезли (потому что, если ваша программа не будет просить ОС сделать что-то глупое, проверять ее не нужно).

Да, это примероптимизация времени выполнения.

9 голосов
/ 05 апреля 2011

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

Моя точка зрения, самоизменяющийся код может быть крайне неприятным для тестирования / отладки и часто имеет скрытые предположения относительно поведениямашина (будь то аппаратная или виртуальная).Более того, система никогда не сможет совместно использовать кодовые страницы между различными потоками / процессами, выполняемыми на (сейчас) многоядерных машинах.Это сводит на нет многие преимущества для виртуальной памяти и т. Д. Кроме того, это делает недействительными оптимизацию веток, проводимую на аппаратном уровне.

(Примечание. Я не включил JIT в категорию самоизменяющегося кода. JIT переводитот одного представления кода к альтернативному представлению, это не изменение кода)

В целом, это просто плохая идея - действительно аккуратная, очень неясная, но очень плохая.

конечно - если все, что у вас есть, это 8080 и ~ 512 байт памяти, вам, возможно, придется прибегнуть к таким методам.

7 голосов
/ 04 апреля 2011

С точки зрения ядра операционной системы каждый Just In Time Compiler и Linker Runtime выполняет самомодификацию текста программы.Ярким примером может служить Google V8 ECMA Script Interpreter.

5 голосов
/ 04 апреля 2011

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

Что такое самоизменяющийся код?Код, который помещает значения в поток выполнения, чтобы его можно было интерпретировать не как данные, а как команду.Конечно, в функциональных языках существует теоретическая точка зрения, что на самом деле нет никакой разницы.Я говорю о том, что я могу сделать это простым способом в императивных языках и компиляторах / интерпретаторах без предположения о равном статусе.

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

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

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