Дизассемблер длин (:n[gvvybQlyj ;lnu)

Перейти к навигации Перейти к поиску

Дизассемблер длин — транслятор, преобразующий машинный код в его длину; аналог дизассемблера, но вычисляющий только размер команды процессора. Обычно применяется с машинным кодом архитектур, допускающих значительную разницу в длине инструкций, обычно из класса CISC. Например, в x86 и x86_64 (Intel и AMD) команда занимает от 1 до 15 байтов[1]. При этом в распространенных RISC архитектурах команда занимает либо всегда 4 байта или допускается использование 2 и 4 байтных команд.

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

Аналогичный «аппарат» существует в процессоре, производя предвыборку команд из памяти и осуществляя конвейеризацию выполняемых команд[2][1]. Первая стадия декодера инструкций в процессорах с внутренним параллелизмом определяет длины инструкций, чтобы найти начало следующих команд[3][4]. В случае успешного определения длин возможна передача на декодирование сразу нескольких инструкций в такт. В ряде реализаций информация о длинах команд может сохраняться в кэше инструкций. Наблюдая за аппаратным декодером длин исследователям удалось найти ранее недокументированные пространства инструкций в некоторых процессорах[5][6].

Программный Дизассемблер длин необходим для:

  • декодирования инструкций дизассемблером;
  • рекомпиляции прологов функций;
  • быстрого анализа команд программы;

Рекомпиляции прологов функций необходима при перехвате вызовов функций и широко используется в Windows (на всех 32х разрядных процессорах совместимых с i80386).

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

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

Примеры дизассемблеров длин можно найти в книге Юань Фэна «Программирование графики для Windows» (дизассемблер длин, представленный там, имеет две ошибки в описании команд x86). Также дизассемблер длин можно найти на сайте wasm.ru

Из-за возможного использования множества префиксов, некоторые сочетания которых могут быть запрещены или игнорироваться, а другие могут изменять длины инструкций, существует ряд широко распространенных ошибок в определении длин для редких сочетаний. Иногда аппаратные реализации разных компаний реализуют такие случаи по-разному[7][8].

Примечания

[править | править код]
  1. 1 2 https://www.agner.org/optimize/blog/read.php?i=25 Архивная копия от 3 октября 2018 на Wayback Machine «The length of an instruction can be anywhere from one to fifteen bytes. If we want to decode several instructions simultaneously, then we have a serious problem. We have to know the length of the first instruction before we know where the second instruction begins.»
  2. United States Patent 8930678
  3. Antonio Gonzalez. 4.4.1 Instruction Length Decoder // Processor Microarchitecture: An Implementation Perspective. — Morgan & Claypool Publishers, 2010. — P. 35. — 116 p.
  4. PC Mag 21 Feb 1995 page 196 «Pentium Alternatives» Архивная копия от 3 ноября 2018 на Wayback Machine «In NexGen’s Nx586, prefetch circuitry determines instruction length and performs alignment of the x86 instructions»
  5. domas @xoreaxeaxeax. Breaking the x86 ISA (англ.) 123. Black Hat (2017). Дата обращения: 2 ноября 2018. Архивировано 4 января 2018 года.
  6. N-version Disassembly: Differential Testing of x86 Disassemblers (англ.). International Conference on Software Testing and Analysis (2010). Дата обращения: 2 ноября 2018. Архивировано из оригинала 3 ноября 2018 года.
  7. domas @xoreaxeaxeax. Breaking the x86 ISA (англ.) 132. Black Hat (2017). Дата обращения: 2 ноября 2018. Архивировано 4 января 2018 года.
  8. Roberto Paleari. N-version Disassembly: Differential Testing of x86 Disassemblers (англ.). International Conference on Software Testing and Analysis (2010). Дата обращения: 2 ноября 2018. Архивировано из оригинала 3 ноября 2018 года.