Доступна ли одношаговая ловушка на win 7?
Я делал с так называемой "цепляй". На самом деле он изменяет разрешение области памяти и перехватывает исключение при обращении к нему, поэтому он может перехватить функцию.
Он использует одношаговую ловушку, которая выглядит следующим образом:
info->ContextRecord->EFlags |= 0x100;
возобновить защиту PAGE_NOACCESS
,
Приложение хорошо работает на win xp, но не так, как исключено на win 7. Оно только замерзло на win 7. Я сильно сомневаюсь, что это из-за "установки одиночного шага", но я не уверен.
Нажмите здесь для прямой ссылки на скачивание пакета с исходным кодом.
1 ответ
Короткий ответ:
Да, флаг с одним шагом является частью архитектуры x86 и также все еще реализуется в Windows 7 через компонент eflags контекста процессора.
Мне удалось загрузить ваш проект, и все отлично работает без изменений в Windows 8 с отключенным UAC. Так что должно работать и на Windows 7. При запуске VEH Hooking Test.exe
он отображает два окна сообщения, после каждого я получаю MessageBoxA
консольный вывод, поэтому крючок сработал. Может быть, попробовать запустить программу от имени администратора в Windows 7?
Длинный ответ:
SEH
обозначает структурированную обработку исключений, но то, что вы описываете, звучит как VEH
векторная обработка исключений.
Перехват VEH - это метод перехвата, который действительно чертовски медленный, поэтому его нельзя реально использовать в ловушках, критичных к производительности, таких как графические перехватчики, например, когда ваши перехватчики обращаются несколько раз в секунду. Обычно используется для одноразовых зацепок. Цель перехвата VEH состоит в том, чтобы быть действительно скрытным. В чужом коде нет памяти, и вам не нужно использовать регистры отладки.
Вот как я бы это реализовал, используя C++.
Сначала вы должны зарегистрировать векторный обработчик исключений. Это глобальный обработчик исключений для процесса. Каждое выброшенное исключение, которое было обработано и перешло в операционную систему, будет перехвачено этим обработчиком.
PVOID pExHandler = AddVectoredExceptionHandler(1, VectoredHandler);
После этого вы должны установить защиту памяти на странице, где ваш HOOK_LOCATION
(адрес для подключения). Новая защита, которую я использую, PAGE_EXECUTE_READ|PAGE_GUARD
, Защищенная страница вызовет исключение при доступе и автоматически удалит защитную защиту после этого. Это исключение не будет обработано никем, поэтому оно будет передано нашему векторному обработчику. После создания исключения страница снова становится доступной. (см. Создание защитных страниц)
Память может быть защищена только в страницах (обычно длиной 0x1000 байт). Вот почему мы не можем защитить только расположение крюков и снизить производительность.
DWORD orgProt;
VirtualProtect(HOOK_LOCATION, 1, PAGE_EXECUTE_READ|PAGE_GUARD, &orgProt);
Теперь для нашего обработчика исключений. Вот как это может выглядеть:
LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS exc)
{
if (exc->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
{
// guard page exeption occured. guard page protection is gone now
if (HOOK_LOCATION == reinterpret_cast<long*>(exc->ContextRecord->Eip)) {
// hook location was hit! call any hook callbacks here
} else {
// hook was not hit and has to be refreshed. set single-step flag
exc->ContextRecord->EFlags |= 0x100;
}
return EXCEPTION_CONTINUE_EXECUTION;
}
if (exc->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
{
// single-step exeption occured. single-step flag is cleared now
// set guard page protection
DWORD oldProt;
VirtualProtect(HOOK_LOCATION, 1, PAGE_EXECUTE_READ|PAGE_GUARD, &oldProt);
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
Если код попадет на защищенную страницу памяти, он выдаст нарушение защитной страницы. Мы проверяем, были ли мы на месте крючка. Если у нас все хорошо и мы можем вызвать обратный вызов. Если мы не находимся в правильном месте, нам нужно каким-то образом восстановить код, но если мы сделаем это сейчас, мы не сможем продвинуться вперед и всегда получим исключение в том же месте и заблокируем приложение. Таким образом, мы устанавливаем флаг процессора одного шага.
Теперь, получив одношаговое исключение, мы можем снова установить защитную защиту, потому что мы продвинулись одной инструкцией. Таким образом, мы всегда можем защитить целевую страницу и не пропустить хиты.
Стоимость составляет два исключения и одну защиту страницы на инструкцию, которая выполняется на целевой странице. Не пытайтесь делать это с подключенным отладчиком. Это сойдет с ума.
Для реальной реализации вам могут потребоваться объекты синхронизации, чтобы избавиться от ловушки без сбоя программы и лучшего управления обработчиками.
Мне очень нравится этот умный механизм, и надеюсь, что некоторые люди узнали об этом немного.