PAGE_GUARD с VirtualProtect не вызывает исключение при доступе к исполнению - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь перехватить функцию, используя PAGE_GUARD, но она не вызывает никаких исключений при вызове страницы / адреса.

void HookMe(){
    printf("Not hooked\n");
}
void GoodFnc(){
    printf("Hooked!\n");
}
long ExceptionHandler(PEXCEPTION_POINTERS ex){
    printf("ExceptionHandler called\n");
}
/*Called by CreateThread in main*/
DWORD WINAPI ExceptionTesting(LPVOID) {
    DWORD old = 0;
    AddVectoredExceptionHandler(1, ExceptionHandler);
    if (VirtualProtect((LPVOID)HookMe, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old))
        printf("PAGE_GUARD set\n");
    //This was for testing:
    //*(char*)0 = 0;//ExceptionHandler gets called when ACCESS_VIOLATION happens
    while (1) {
        HookMe();
        Sleep(1000);
    }
    return 0;
}

Приведенный выше код покажет только PAGE_GUARD set, а затем Not hooked каждую секунду, не вызывая каких-либо исключений.

Я также убедился, что HookMe() находится на странице памяти, отличной от ExceptionHandler(...) и ExceptionTesting(LPVOID)

Причинение любого видаисключение, такое как ACCESS_VIOLATION (как видно из комментария над бесконечным циклом), приведет к вызову ExceptionHandler.

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

В документации для VirtualProtect говорится, что защищаемые адреса должны быть частью зарезервированного региона, полученного с помощью VirtualAlloc (или VirtualAllocEx).Код в вашей программе не был размещен таким образом.

Кроме того, защита выполняется на основе страниц (обычно 4 КБ), поэтому вероятно, что весь кода в приведенном выше примере будет защищени охранник сразу же уйдет, когда вызов на VirtualProtect вернется, а не тогда, когда будет Hook.

0 голосов
/ 28 мая 2018

о VirtualProtect

Изменяет защиту в области зафиксированных страниц в виртуальном адресном пространстве вызывающего процесса.

PAGES - не один байт.мы можем установить атрибут PAGE_GUARD как минимум только на байт страницы (0x1000).в результате, когда вы пытаетесь установить PAGE_GUARD для какой-либо функции - вы устанавливаете атрибут guard не только для него, но и для множества байтов вокруг него (до и после).в случае, если код такой ваш (в любом случае, ваш код является псевдокодом, который даже не компилируется) - более быстрое исключение будет только после VirtualProtect return - при следующей инструкции после вызова.если вы хотите, чтобы страница защиты влияла только на одну функцию - вам нужно поместить ее в отдельный раздел exe, скажем, с помощью #pragma code_seg.Также могу заметить - что не нужно никаких бесконечных циклов или отдельных потоков, созданных для теста

//#pragma code_seg(".guard")
void HookMe(){
    MessageBoxW(0, 0, L"HookMe", MB_ICONINFORMATION);
}
#pragma code_seg()

LONG NTAPI ExceptionHandler(::PEXCEPTION_POINTERS pep)
{
    if (pep->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
    {
        WCHAR msg[64];
        swprintf(msg, L"guard violation at %p (%p)", pep->ExceptionRecord->ExceptionAddress, HookMe);
        MessageBoxW(0, msg, L"ExceptionHandler", MB_ICONWARNING);
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

void gtest()
{
    if (PVOID pv = AddVectoredExceptionHandler(TRUE, ExceptionHandler))
    {
        ULONG op;
        if (VirtualProtect(HookMe, 1, PAGE_EXECUTE_READ|PAGE_GUARD, &op))
        {
            HookMe();
        }
        RemoveVectoredExceptionHandler(pv);
    }
}
0 голосов
/ 28 мая 2018

Возможно, в зависимости от вашего компилятора, вызов HookMe является встроенным.Проверьте сгенерированный код.Вы должны быть в состоянии победить это с чем-то вроде __declspec(noinline) в объявлении HookMe.(MS VC ++).Обратите внимание, что вы можете взять адрес функции, даже если он встроен во все вызовы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...