Обращение к памяти с PAGE_NOACCESS

Тема в разделе "WASM.WIN32", создана пользователем SnugForce, 29 сен 2005.

  1. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Регистрация:
    2 май 2005
    Сообщения:
    373
    Адрес:
    Из домУ
    Делаю так ошибка появляется: "Память не может быть read"
    Код (Text):
    1.  
    2. VirtualProtect(@ForCopy, 1, PAGE_NOACCESS, Old);
    3. try
    4.   ForCopy;  
    5. except end;
    6.  


    Делаю так, прога вылетает...
    Код (Text):
    1.  
    2. try
    3.   VirtualProtect(@ForCopy, 1, PAGE_NOACCESS, Old);
    4.   try
    5.     ForCopy;  
    6.   except end;
    7. except end;
    8. Странно это...
    9.  
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ничего странного, если твоя ForCopy расположена в той же 4K странице, что и вызов VirtualProtect (думаю ты понимаешь, что доступ устанавливается не для одного байта, а для всей страницы, в которой лежит этот байт).

    В этом случае ошибка возникает уже при возврате из VirtualProtect до вызова ForCopy. В первом варианте try\except на возврат не установлен и исключение передается в финальный дефолтный обработчик приложения, который расположен в другой 4K странице. Во втором варианте локальный обработчик try\except установлен, но лежит поблизости в той же заблокированной странице. Повторное исключение при вызове обработчика это уже слишком и ось просто прибивает твою прогу (имхо).
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    leo

    А разве исключение будет не "cannot be to execute"?
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    IceStudent

    При обращении к PAGE_NOACCESS возникает #GP, т.е. Access Violation. Откуда у SnugForce берется "Память не может быть read" - нужно у него спросить ;)
     
  5. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Регистрация:
    2 май 2005
    Сообщения:
    373
    Адрес:
    Из домУ
    Хм... понял.

    Хотя у меня выскакивает: "Инструкция по адресу ... обратилась к памяти по адресу ... . Память не может быть read"
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    leo

    Не, спорить не буду, просто по идее он же обращается на читая, а пытаясь вернуться в код, на который выставлено PAGE_NOACCESS..
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    SnugForce

    Ну дык посмотри в отладчике, на какой инструкции происходит ошибка. Может тут еще какие собаки зарыты или просто сообщение выводится неточное.
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Смоделировал ситуацию и тоже получаю сообщение типа Read of address ..., хотя это адрес команды xor eax,eax (стандартное начало try\except в дельфях) и естественно его никто не read, а лишь execute. Так что это имхо не более чем общая фраза. Кстати в пошаговом режиме Оля возвращается из ret VirtualProtect на xor, но при попытке исполнить этот xor кричит об access violation
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    IceStudent

    > А разве исключение будет не "cannot be to execute"?

    А ты когда-будь встречал такие сообщения ?

    Насколько я понимаю такое возможно только при наличии аппаратной поддержки DEP (предотвращение исполнения данных). Без такой поддержки процессор распознает только два варианта доступа к странице read-only или read-write. Запретить read и execution процессору явно нельзя, можно только сделать страницу недоступной вообще - сбросить флаг present или установить резервные флаги, что видимо ось и делает при установке атрибута PAGE_NOACCESS. При обращении к инвалидной странице проц выдает исключение #PF (page fault) и в error-коде указывает тип доступа, при котором произошла ошибка - read или write (никакого execute не предусмотрено). Поэтому имхо и вываливаются два стандартных варианта сообщения "Память не может быть read (или write)". Ну а поскольку при исполнении ошибка происходит при попытке чтения кода в кэш, то ес-но это read ;)



    Во втором варианте кода, когда VirtualProtect заключена в try\except, происходит двойной fault и программу приходится прибивать. В XP, кстати при этом срабатывает программный DEP - прежде чем передать управление SEH-обработчику ось проверяет валидность его адреса. Поэтому при включенном DEP прога умирает не по тихому, а после серии виндовых предупреждений, разъяснений и предложений :))
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine


    А, теперь понятно.
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    > "никакого execute не предусмотрено"

    А вот в AMD64 предусмотрено - в PF error-коде есть доп. флажок I/D (instruction/data), который установлен если ошибка произошла при фетче инструкций. Все течет, все изменяется, однако ;)