IDP

eXeL@B DVD

Материал из Справочник исследователя программ

Перейти к: навигация, поиск

IDP - инвалидация ссылок для генерации #AV(хард. #PF и #GP) и откатом фолта посредством исполнения инструкции вызвавшей фолт в смещённом сегменте. Позволяет выполнить динамический захват кода без изменения кодосекций. По сути один из способов получить управление гдето в целевой процедуре.

Допустим имеется глобальная переменная, которая находится в сегменте R/W и содержит адрес структуры(ссылку на неё). В эту переменную загружается ссылка на не доступный регион памяти(PAGE_NOACCESS), который расположен по адресу ниже адреса исходной структуры(обычно в первых 16К). При обращении к этой структуре через ссылку в переменной возникнет #AV и будет развёрнуто. Диспетчер исключений проверяет адрес к которому произошло обращение и если это целевая структура, то изменяет сегмент(посредством загрузки селектора нового сегмента в сегментные регистры) таким образом, дабы обращение произошло к оригинальной структуре(для этого заранее создаётся дескриптор в LDT и в переменную загружается смещение структуры в сегменте). После чего инструкция перезапускается и обращение происходит к исходной структуре(сегмент смещается вверх, адрес структуры Base:[Offset], база не нулевая и равна разнице смещений). Перезапуск выполняется в пошаговом режиме(трассировка) для восстановления сегментных регистров после исполнения инструкции. Далее код исполняется с оригинальными селекторами. Эта фаза генерации останова(доступ к структуре происходит раньше, чем управление будет передано на целевой код). IDP является частным способом получить управление, могут использоваться иные способы, например вызов непосредственно калбэков или генерация других исключений, например отладочных(посредством DbgPrint()). Далее выполняется непосредственно захват целевого кода.

Фаза захвата целевого кода по сути отложенный его вызов. Может быть исполнен несколькими способами:

o Динамический.
  - Трассировка.
  - Маршрутизация.
  - Хардварные брейки.
o Статический.
  - Копирование кода.
  - Перемещение кода посредством его морфинга.

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

Маршрутизация - трассировка с пропусканием процедур. Код трассируется до входа в процедуру, после этого заменяется в стеке адрес возврата из неё и трассировка прекращается. После возврата из процедуры трассировка вновь продолжается и так до целевого кода.

Хардварные брейки реализуются посредством регистров Dr*. Не желательно для применения.

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

Технология эффективна в обоих модах. Пользовательский движок можно увидеть тут.

Источник — «https://exelab.ru/faq/IDP»