Для начала я кратко пробегусь по явно неверным ответам:
VirtualProtect пишет в OldProtectionCode прежде чем читает новое значениеТретий аргумент передаётся в VirtualProtect по значению, поэтому любые изменения четвёртого аргумента во время работы функции не влияют на третий аргумент.
Если мы под отладчиком, и на начало функции ATargetFunction поставлена точка останова, то там код уже изменён, дебажий хук стоит.Автор ответа сам же и указал: "что может сломаться - непонятно". Точка останова просто будет убрана (перезаписана JMP).
мне очень любопытно, что будет если вашу функцию натравить на нея самою. Не выдернет она у себя из под ног право на исполнение себя самой?Надо понимать, что "задачки" возникают исключительно из практики. Кто будет ставить хук на функцию установки хука?
что будет, если скармливается функция размером меньше 8 байт, стоящая на самом конце стpаницы, и следующей стрaницы просто-таки не существует ( ну или guard page, etc) ?Мне кажется, что автор пропустил
const MaxPossibleSize = 8;и
размер ATargetFunction больше 8-ми байт
FlushInstructionCache(GetCurrentProcess, ATargetFunction, MaxPossibleSize)Это была маленькая ловушка для отвлечения внимания. Отсутствие
сказал MSDN :)
FlushInstructionCache
- первое, что должно броситься в глаза. Однако вот вопрос: что будет, если мы не вызовем FlushInstructionCache
? Это значит, что потенциально в кэше процессора будет находиться старая команда, до её перезаписи. Поэтому при ближайшем вызове ATargetFunction
будет вызван не наш JMP
, а её оригинальный код. Понятно, что это не приведёт к Access Violation, а просто не сработает хук. Хотя отсутствие FlushInstructionCache
- это действительно ошибка, но это не проблема этой задачки.Собственно, правильный ответ был назван многими, хотя никто не догадался о самом очевидном сценарии. Итак, действительно, изменение атрибутов защиты 8-ми байт кода изменит атрибут защиты не только этих восьми байт, но и целой страницы памяти (обычно - 4 кб), потому что одна страница памяти является минимальной единицей для системной памяти. Чем же это грозит? Дело в том, что мы можем устанавливать хук на системную функцию. А эта функция... может быть расположена рядом с самой
VirtualProtect
! Иными словами, первый вызов VirtualProtect
изменит атрибут защиты страницы с целевой функцией (а заодно - и с самой VirtualProtect
) с PAGE_EXECUTEREAD
на PAGE_READWRITE
, что, конечно же, позволит нам записать туда JMP
, но второй вызов VirtualProtect
вылетит с Access Violation, потому что попытается выполнить код со страницы с атрибутами PAGE_READWRITE
, где нет права на выполнение кода (см. также).Исправление заключается в изменении атрибута на
PAGE_EXECUTEREADWRITE
.
>>> хотя никто не догадался о самом очевидном сценарии
ОтветитьУдалитьКак никто, а некий FLABER один в один описал. В третьем комментарии. А в первом было высказано предположение что скорее всего это PAGE_EXECUTE_READWRITE
Под "самым очевидным сценарием" подразумевалась установка хука на функцию ядра. А на проблему атрибутов защиты указало несколько человек.
ОтветитьУдалить