Вопрос

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

Это было полезно?

Решение

NOP служат нескольким целям:

  • Они позволяют отладчику размещать точку останова на строке, даже если она объединена с другими в сгенерированном коде.
  • Это позволяет погрузчику исправить прыжок со смещением цели разного размера.
  • Это позволяет выровнять блок кода по определенной границе, что может быть полезно для кэширования.
  • Это позволяет выполнять инкрементальное связывание для перезаписи фрагментов кода вызовом нового раздела, не беспокоясь об изменении общего размера функции.

Другие советы

Вот как nops используются при отладке:

Nops используются компиляторами языка (C #, VB и т. д.) для определения неявных точек последовательности. Они сообщают компилятору JIT, где обеспечить соответствие машинных инструкций инструкциям IL.

Запись в блоге Рика Байера на DebuggingModes.IgnoreSymbolStoreSequencePoints , объясняет несколько деталей.

C # также помещает Nops после инструкций вызова, так что местом возврата сайта в источнике является вызов, а не строка после вызова.

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

Это также может ускорить выполнение кода при оптимизации под конкретные процессоры или архитектуры:

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

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

Чувак!«Нет-оп» — это круто!Это инструкция, которая ничего не делает, но отнимает время.В смутные темные века вы использовали бы его для микрорегулировки времени в критических циклах или, что более важно, в качестве наполнителя в самомодифицирующемся коде.

В одном процессоре, над которым я работал недавно (в течение четырех лет), использовался NOP, чтобы убедиться, что предыдущая операция завершена до начала следующей операции. Например:

загрузить значение для регистрации (занимает 8 циклов) № 8 добавить 1 для регистрации

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

Другое использование заключалось в заполнении исполнительных блоков, таких как векторы прерываний, которые должны были быть определенного размера (32 байта), потому что адрес для вектора 0 был, скажем, 0, для вектора 1 0x20 и т. д., поэтому компилятор поместил NOP там, если нужно.

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

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

Nop важен для использования уязвимостей переполнения буфера.

Как сказал ddaa, nops позволяет учесть дисперсию в стеке, поэтому при перезаписи адреса возврата он переходит на салазки nop (много nops в строке), а затем корректно выполняет исполняемый код, а не переход к некоторому байту в инструкции, которая не является началом.

50 лет слишком поздно, но эй.

Nop полезны, если вы набираете код сборки вручную. Если вам нужно было удалить код, вы можете удалить старые коды операций.

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

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

В настоящее время с компиляторами методы больше не имеют никакого смысла.

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

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

Несколько необычное использование: слайды NOP , используемые в эксплойты переполнения буфера.

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

По крайней мере, это одно из их традиционных применений.

Это не ответ на ваш конкретный вопрос, но в старые времена вы могли использовать NOP для заполнения время задержки перехода , если вам не удалось заполнить его полезной инструкцией.

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

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

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

Я использовал NOP для автоматической регулировки задержки, накопленной после входа в ISR. Очень удобно прибивать время до смерти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top