Пишу на дельфи, детям и женщинам с чувствительной психикой не читать. Собственно сабж: при обращении к странице с атрибутом PAGE_GUARD не возникает обработки исключения, хотя сам PAGE_GUARD отрабатывает как положено и при следующем обращении к этой странице она становится доступной. ОС Windows 7 x64 RTM. Код (Text): function AddVectoredExceptionHandler(FirstHandle: ULONG; VectoredHandler : Pointer): PVOID; stdcall; external 'kernel32.dll'; var pHandler, pMem: Pointer; s: string; numWr: DWORD; // собственно сам обработчик, который просто фиксирует исключение function MyVectoredHandler(ExceptionInfo: PExceptionPointers): Longint; stdcall; begin writeln('Vectored exception handled'); end; begin // добавляем обработчик первым в цепочке, здесь всё ОК pHandler := AddVectoredExceptionHandler(1, @MyVectoredHandler); if pHandler = nil then MessageBox(0, PChar(SysErrorMessage(GetLastError)), 'Last Error', MB_OK); // здесь тоже всё ОК, PAGE_GUARD назначается как и положено pMem:=VirtualAlloc(nil,4,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE or PAGE_GUARD); if pMem=nil then writeln('pMem nil'); s:='1234'; // запись в страницу с PAGE_GUARD WriteProcessMemory(GetCurrentProcess, pMem, @s[1], 4, numWr); // всё ОК, записано 0, но эксепта в обработчике почему-то нету... Writeln(numWr);
Пишет сервис же, из ядра. Точнее, пытается писать – но наталкивается на PAGE_GUARD, в ядре возникает сепшн, ядром обрабатывается, PAGE_GUARD снимается, и сервис тут же возвращает ошибку. Всё в соответствии с msdn. Если в данном случае попытаться напрямую записать\считать из страницы с PAGE_GUARD (не через сервис), то сепшн будет получен в юзермоде и хендлер _будет_ вызван. P.S. Если удастся воспроизвести ситуацию, когда сервис вернёт ошибку, а PAGE_GUARD не будет снят – просьба сообщить.
Вопрос - зачем так делать? Никогда не понимал, зачем люди вызывают Read/WriteProcessMemory с псевдохендлом текущего процесса. Неужели memcpy() (а принеобходимости + VirtualProtect) отменили?
В случае если несколько потоков обращаются к сторожевой странице или ядро обращается к ней, следует полностью запретить доступ(PAGE_NOACCESS).
Great Не совсем понял что это значит. Кстате обратится к сторожевой странице без генерации сепшена и снятием атрибута PAGE_GUARD можно просто, загрузить начало и конец сторожевого региона в TIB(TEB.Tib.StackBase и StackLimit), после чего можно успешно юзать память
Эээ, народ, понятно, что в пятницу все отдыхали и утром голова болит, но сейчас днём может кто-то конкретно объяснить что происходит касательно кода в посте #1 без вопросов зачем так делать и как это можно обойти. +++ Точнее подтвердить то, что написано в посте #2 и таким образом получается я никак не могу обработать исключение из юзермода при записи кем-то|чем-то в юзермоде в мой процесс по адресу сторожевой страницы. P.S. Все эти извращения как думаю многие догадались для юзермодного запрета записи в память своего процесса с возможностью использования на х86_64.
#1 Код (Text): function AddVectoredExceptionHandler(FirstHandle: ULONG; VectoredHandler : Pointer): Pointer; stdcall; external 'kernel32.dll'; var pMem: Pointer; dWrd : DWORD; function MyVectoredHandler(ExceptionInfo: Pointer): Longint; stdcall; begin MessageBox(0,'Exception',0,0); end; begin AddVectoredExceptionHandler(1, @MyVectoredHandler); pMem:=VirtualAlloc(nil,4,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE or PAGE_GUARD); dWrd := 1233; asm push eax mov eax, pMem push dWrd pop dword ptr [eax] pop eax end; Readln; end. хз...
чот протупил) Код (Text): AddVectoredExceptionHandler(1, @MyVectoredHandler); pMem:=VirtualAlloc(nil,4,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE or PAGE_GUARD); PDWORD(pMem)^ := 123; Readln;
d2k9 Вам Sol_Ksacap понятно обьяснил почему атрибут снимается. Любой сервис, который юзает память из юзермпэйса ставит сех в начале своей работы, далее при обращении к сторожевой странице сепшен обрабатывается в этом сех и управление возвращается. При этом код ошибки будет возвращён, никакой диспетчер исключений не будет вызван.