logo
622231 / 622221с / очн 622221с / ПАЗИ 622221с / КЛ_ПАЗИ

Лекция 30 Использование недокументированных инструкций и недокументированных возможностей процессора

Один из подходов, используемый для затруднения отладки и дизассемблировании программ, заключается в привлечении редко используемых инструкций центрального процессора (ЦП), недокументированных инструкций, или инструкций, имеющих скрытый результат [Error: Reference source not found]. Не все злоумышленники хорошо знакомы с подобными инструкциями и скрытыми возможностями ЦП, что затрудняет исследование ими программ. Недостаток данных методов – жесткая привязка к процессору. Кроме этого, не гарантируется поддержка недокументированных инструкций в будущих процессорах, а значит совместимость с ними разработанных защит.

Достаточно часто для защиты ПО от исследования используют недокументированное использование префиксов инструкций.

Префиксы в кодах инструкций делятся на следующие типы:

  1. Префиксы блокировки и повторения – говорят о том, что код инструкции относится к действиям блокировки или повторения.

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

Табл. 8.2. Соответствия префиксов и кодируемых ими сегментов

Значение префикса

Сегмент

2Eh

CS

36h

SS

3Eh

DS

26h

ES

64h

FS

65h

GS

3. Префиксы переопределения размеров операндов (префикс 66h). Данный префикс используется в 16-разрядном режиме для манипулирования с 32-битными операндами и наоборот.

4. Префиксы переопределения размеров адреса (префикс 67h).

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

1. Недокументированное использование префикса переопределения размеров операндов. Согласно стандарту он используется только при наличии в команде каких-либо операндов. Однако на практике для реального процессора данный префикс может быть поставлен перед любой командой, и это будет работать на реальном процессоре. Например, реальный процессор примет инструкцию 0x66 CLI (использование префикса перед оператором запрещения прерываний). В связи с тем, что данная возможность не документирована, то, как правило, отладчики и дизассемблеры не принимают подобные инструкции и отказываются корректно интерпретировать подобный код.

2. То же самое следует сказать и про префиксы переопределения размеров адреса. Данные префиксы согласно документации используются только в командах, оперирующих с адресами памяти. Их использование с другими командами не документировано, но процессор будет выполнять эти команды. В качестве примера такой инструкции можно привести инструкцию 0x67 STI.

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

4. Использование дублирующих префиксов, то есть запись префиксов вида 0x66, 0x66 непосредственно перед командой. Хотя фирма INTEL не гарантирует корректную работу своих процессоров при обнаружении такого рода инструкций, но фактически все процессоры правильно интерпретируют данные ситуации. Иное дело – отладчики и дизассемблеры, которые спотыкаются и начинают некорректно вести себя.

Следует отметить также, что процессором INTEL корректно выполняются и инструкции вида DS:FS:CS:Mov ax, [100] (последний префикс перекрывает все остальные), а многие отладчики и дизассемблеры сбиваются при их анализе.

5. Обращение к недокументированным регистрам. В процессорах INTEL регистры в настоящее время кодируются тремя битами следующим образом (таблица 8.3).

Табл. 8.3. Кодирование регистров в инструкциях

Код

Инструкция

000

ES

001

CS

010

SS

011

DS

100

FS

101

GS

110

Зарезервирован

111

Зарезервирован

Две последние кодовые комбинации (110 и 111) в настоящее время зарезервированы и не используются. При попытке их использования вызывается исключительная ситуация 06h, которую можно перехватить. Отладчики же и дизассемблеры при встрече с подобными инструкциями начинают вести себя странно и непредсказуемо. Одни не генерируют при этом прерывания, чем и выдают себя, другие начинают некорректно работать. Поведение же дизассемблеров в этом случае тоже разнообразно. Ниже приведен пример того, как различные дизассемблера воспринимают подобные инструкции.

HIEW

8E ???

F8 clc

C3 retn

Qview

8EF8 mov !s, ax

C3 ret

IDA Pro

Db 8E

Db 0F8

DB C3

Несуществующие регистры можно эмулировать в обработчике прерывания int 06h.