Не пойму.
От: Keith  
Дата: 25.06.04 22:53
Оценка:
Вот из Рихтера:

Закрытый раздел размером 64 Кб (только Windows 2000)

Этот раздел заблокирован, и любая попытка обращения к нему приводит к нарушению доступа Microsoft резервирует этот раздел специально, чтобы упростить внутреннюю реализацию операционной системы. Вспомните, когда Вы передаете Windows-функции адрес блока памяти и его размер, то она (функция), прежде чем приступить к работе, проверяет, действителен ли данный блок. Допустим, Вы написали код:

BYTE bBuf[70000]; 
DWORD dwNumBytesWritTen; 
WriteProcessMemory(GetCurrentProcess(), (PVOID) 0x7FFEEE90, bBuf, sizeof(bBuf), &dwNumBytesWntten);


В случае функций типа WriteProcessMemory область памяти, в которую предполагается запись, проверяется кодом, работающим в режиме ядра, — только он имеет право обращаться к памяти, выделяемой под код и данные режима ядра (в 32-разрядных системах — по адресам выше 0x80000000) Если по этому адресу есть память, вызов WriteProcessMemory, показанный выше, благополучно запишет данные в ту область памяти, которая, по идее, доступна только коду, работающему в режиме ядра. Чтобы предотвратить это и в то же время ускорить проверку таких областей памяти, Microsoft предпочла заблокировать данный раздел, и поэтому любая попытка чтения или записи в нем всегда вызывает нарушение доступа


Никак не могу понят, что имелось ввиду? Как этот кусок в 64к способствует тому, что я не могу писать в память ядра? Если имеется ввиду, что этот кусок является гранью между моей памятью и памятью ядра, и служит guard'ом для моих увеличивающихся указателей, то как борятся с тем, что я просто буду писать в память, находящуюся за этим куском?
Re: Не пойму.
От: MaxSem  
Дата: 26.06.04 07:54
Оценка:
Здравствуйте, Keith, Вы писали:

K> Никак не могу понят, что имелось ввиду? Как этот кусок в 64к способствует тому, что я не могу писать в память ядра? Если имеется ввиду, что этот кусок является гранью между моей памятью и памятью ядра, и служит guard'ом для моих увеличивающихся указателей, то как борятся с тем, что я просто буду писать в память, находящуюся за этим куском?


Просто это защита от дурака, а не от злоумышленника. Она предназначена для защиты от случайной записи: когда вы, записывая не туда куда надо, дойдёте до этого блока, система вас остановит, не дожидаясь, пока вы начнёте затирать память ядра. Только-то и всего.
Re[2]: Не пойму.
От: Keith  
Дата: 27.06.04 20:51
Оценка:
MS>Просто это защита от дурака, а не от злоумышленника. Она предназначена для защиты от случайной записи: когда вы, записывая не туда куда надо, дойдёте до этого блока, система вас остановит, не дожидаясь, пока вы начнёте затирать память ядра. Только-то и всего.

Что-то дурак очень односторонний. Кроме как превышать границу своих данных больше и не умеет ничего делать.
А если случайно сгенерится неправильный указатель в область лежащую за пределами этого куска, то что будет? Какая принципиальная разница между этим куском в 64k(кстати, нафига такой большой?) и памятью, лежащей за ним?
Re[3]: Не пойму.
От: Vamp Россия  
Дата: 28.06.04 07:08
Оценка:
K>А если случайно сгенерится неправильный указатель

Как он может случайно сгененироваться? Неправильная обращение обычно происходит при выходе за границы массива, и вот тут блок-страж как раз кстати.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Не пойму.
От: SergH Россия  
Дата: 28.06.04 10:10
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Как он может случайно сгененироваться?


Например, обратился за пределы массива и изменил при этом следующую переменную (всё происходит в стеке). А в ней был указатель..
Делай что должно, и будь что будет
Re[4]: Не пойму.
От: Keith  
Дата: 28.06.04 20:10
Оценка:
K>>А если случайно сгенерится неправильный указатель
V>Как он может случайно сгененироваться?
Очень легко. Есть такие указатели, которые называют дикими. Или, например, указателю присваевается значение, которое не является указателем.

V>Неправильная обращение обычно происходит при выходе за границы массива, и вот тут блок-страж как раз кстати.

А если необычно?
Re[5]: Не пойму.
От: Andrew S Россия http://alchemy-lab.com
Дата: 28.06.04 21:21
Оценка:
V>>Как он может случайно сгененироваться?

SH>Например, обратился за пределы массива и изменил при этом следующую переменную (всё происходит в стеке). А в ней был указатель..


Похоже, на самом деле Рихтер лукавит и говорит совсем не о том, для чего на самом деле эти предохранительные блоки. Очевидно, любая попытка записать в адреса выше второго гигабайта из user-mode невозможна и приложение, которое осуществит такую попытку, вызовет исключения доступа. Другое дело — адреса ниже второго гигабайта. Тут в случае наличия страницы запись вполне возможна. Однако хотелось бы уже на этапе отладки приложения отследить "стремные" действия, связанные с наиболее частыми ошибками программирования (например, с нулевыми или отрицательными указателями). Для этого как раз и предназначены эти блоки. Согласитесь — гораздо приятнее увидеть ацесс виолятион на этапе отладки, нежели получить трудновоспроизводимый баг у пользователя.
WriteProcessMemory — совершенно другая песня, и, очевидно, guard pages в данном случае только малая часть того, что проверяет система.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: Не пойму.
От: Slava Antonov Россия http://deadbeef.narod.ru
Дата: 29.06.04 02:01
Оценка:
Hello Andrew S, you wrote:

> на самом деле эти предохранительные блоки. Очевидно, любая попытка

> записать в адреса выше второго гигабайта из user-mode невозможна

Возмножна, если АП разделено в отношении 3/1, а не 2/2.
Для этого есть соответсвующий ключ в boot.ini. Также это есть на каком-то
Windows Server

--
Всего хорошего, Слава
http://slava.users.otts.ru
Posted via RSDN NNTP Server 1.9 beta
Re[7]: Не пойму.
От: Andrew S Россия http://alchemy-lab.com
Дата: 29.06.04 08:33
Оценка: +1
>> на самом деле эти предохранительные блоки. Очевидно, любая попытка
>> записать в адреса выше второго гигабайта из user-mode невозможна

SA>Возмножна, если АП разделено в отношении 3/1, а не 2/2.

SA>Для этого есть соответсвующий ключ в boot.ini. Также это есть на каком-то
SA>Windows Server

Вот только не надо передергивать
Это все понятно, что соотношение адресных пространств user\kernel может быть разным. Для этого, помимо ключей в boot.ini, есть еще и опция в заголовке PE ( /LARGEADDRESSAWARE). Мы ведь говорим про совсем другие вещи, верно?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Не пойму.
От: Valerio Россия linkedin.com/in/boronin
Дата: 29.06.04 08:57
Оценка:
Здравствуйте, Keith, Вы писали:

K> Никак не могу понят, что имелось ввиду? Как этот кусок в 64к способствует тому, что я не могу писать в память ядра? Если имеется ввиду, что этот кусок является гранью между моей памятью и памятью ядра, и служит guard'ом для моих увеличивающихся указателей, то как борятся с тем, что я просто буду писать в память, находящуюся за этим куском?


этот регион предотвращает передачу потоками буферов через границу между um\km (user\kernel mode)/ Стартовый адрес в MmUserProbeAddress (0х7FFF000 на х86 с 2 Гб user space и 0xBFFF000 с 3Гб — SergH, привет )

Цифра растет ИМХО из того факта, что гранулярность выделения памяти (see GetSystemInfo) 64Кб — так было задумано для того чтобы быть готовым к поддержке будущих CPU с размером страницы 64Кб. Кстати выравнивание таких регионов также происходит в соотв с гранулярностью выделения памяти, а вот размер адресного пространства кратен уже странице.

Подчеркну, что здесь речь о резервировании региона адресного пространства и это не относится к режиму ядра — там все нормально, гранулярность 1 страница.
... << Rsdn@Home 1.1.4 beta 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[6]: Не пойму.
От: SergH Россия  
Дата: 29.06.04 09:02
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Похоже, на самом деле Рихтер лукавит и говорит совсем не о том, для чего на самом деле эти предохранительные блоки. Очевидно, любая попытка записать в адреса выше второго гигабайта из user-mode невозможна и приложение, которое осуществит такую попытку, вызовет исключения доступа. Другое дело — адреса ниже второго гигабайта. Тут в случае наличия страницы запись вполне возможна. Однако хотелось бы уже на этапе отладки приложения отследить "стремные" действия, связанные с наиболее частыми ошибками программирования (например, с нулевыми или отрицательными указателями). Для этого как раз и предназначены эти блоки. Согласитесь — гораздо приятнее увидеть ацесс виолятион на этапе отладки, нежели получить трудновоспроизводимый баг у пользователя.


И всё-таки про верхний блок я не въехал Без этого блока память была чётко разделена на две части — куда можно обращаться и куда нельзя. И это стабильно, как во время отладки, так и у заказчика. С этим блоком, в общем-то таже фигня — есть две области, в обдну лазать можно, в другую нельзя. И тоже как при отладке, так и у заказчика. Причём конфигурация областей не поменялась — снизу можно, сверху нельзя (введение нижнего блока меняет конфигурацию, но оно мне и понятно), поменялся только адрес границы. И где здесь упрощение отладки?
Делай что должно, и будь что будет
Re[7]: Не пойму.
От: Andrew S Россия http://alchemy-lab.com
Дата: 29.06.04 09:19
Оценка:
SH>И всё-таки про верхний блок я не въехал Без этого блока память была чётко разделена на две части — куда можно обращаться и куда нельзя. И это стабильно, как во время отладки, так и у заказчика. С этим блоком, в общем-то таже фигня — есть две области, в обдну лазать можно, в другую нельзя. И тоже как при отладке, так и у заказчика. Причём конфигурация областей не поменялась — снизу можно, сверху нельзя (введение нижнего блока меняет конфигурацию, но оно мне и понятно), поменялся только адрес границы. И где здесь упрощение отладки?

Верхний блок отлавливает обращение к диапазону 7FFE0000 — 7FFFFFFF в стандартной конфигурации. Вероятно, такие адреса тоже часто бывают ошибочными, как и нулевые (пример я с ходу придумать не могу, но выглядят они подозрительно ). Ну, или в майкрософт так решили По крайней мере, во всей доступной литературе они описываются как блоки, позволяющие отлавливать часто встречающиеся ошибки программирования. Насчет того, что Рихтер говорит про упрощение проверки, например, в WriteProcessMemory — это, по моему мнению, глупость — нам и так известен адрес, куда мы пишем и размер блока, поэтому проверить простым условием это гораздо проще. А все остальное попадает под определение отлова ошибок программинга.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Не пойму.
От: SergH Россия  
Дата: 29.06.04 10:01
Оценка:
Здравствуйте, Valerio, Вы писали:

V>этот регион предотвращает передачу потоками буферов через границу между um\km (user\kernel mode)

V>Стартовый адрес в MmUserProbeAddress (0х7FFF000 на х86 с 2 Гб user space и 0xBFFF000 с 3Гб — SergH, привет )

А теперь ешё раз для тех кто в танке? Буферы — это те, что в запросах ввода-вывода? Они же вроде выделяются пользовательским приложением. Типа я вызываю ReadFile а перед этим выделяюдля него буфер.. В общем объясни пожалуйста ещё раз.

И почемк мне привет, ктстати?

V>Цифра растет ИМХО из того факта, что гранулярность выделения памяти (see GetSystemInfo) 64Кб — так было задумано для того чтобы быть готовым к поддержке будущих CPU с размером страницы 64Кб. Кстати выравнивание таких регионов также происходит в соотв с гранулярностью выделения памяти, а вот размер адресного пространства кратен уже странице.


Да, это я знаю, с этим я согалсен.
Делай что должно, и будь что будет
Re[3]: Не пойму.
От: Valerio Россия linkedin.com/in/boronin
Дата: 29.06.04 11:46
Оценка: 6 (1) +1
V>>этот регион предотвращает передачу потоками буферов через границу между um\km (user\kernel mode)
V>>Стартовый адрес в MmUserProbeAddress (0х7FFF000 на х86 с 2 Гб user space и 0xBFFF000 с 3Гб — SergH, привет )

SH>А теперь ешё раз для тех кто в танке? Буферы — это те, что в запросах ввода-вывода? Они же вроде выделяются пользовательским приложением. Типа я вызываю ReadFile а перед этим выделяюдля него буфер.. В общем объясни пожалуйста ещё раз.

никто не мешает ошибочно\преднамеренно передать плохой адрес\размер буфера

Если запись (WriteProcessMemory тот же, на который у Рихтера ссылаются) пойдет из um в ядро непрерывно, она прервется при доступе к этой страничке.

MmUserProbeAddress используется еще вот для чего часто:

драйверу (через METHOD_NEITHER например) напрямую отдаются user mode buffers которые будут отображаться в ядро. Соотв такие вещи там перед использованием надо оборачивать в try/except блоке проверками на ProbeForRead/ProbeForWrite (что и делают соотв Zw* ф-ии для usermode буферов)

Соотв проверки на валидность элементарные:
        cmp     esi, _MmUserProbeAddress     ; check if user address
        jae     notuseraddress               ; if ae, then not user address


Короче опираясь на эту переменную всегда можно проверить валидность адреса для um\km и сопоставить с режимом доступа.

SH>И почемк мне привет, ктстати?

Сергей, прошу прощения, привет предназначался Славе Антонову получается ( это из-за Re[6]: Не пойму.
Автор: Slava Antonov
Дата: 29.06.04
). Но и тебе привет тоже
... << Rsdn@Home 1.1.4 beta 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[4]: Не пойму.
От: SergH Россия  
Дата: 29.06.04 12:36
Оценка:
Здравствуйте, Valerio, Вы писали:

V>никто не мешает ошибочно\преднамеренно передать плохой адрес\размер буфера


Угу, значит буферы эти.

V>MmUserProbeAddress используется еще вот для чего часто:


...

Понятно. Непонятно, почему MmUserProbeAddress нельзя было сделать 0x80000000 (ну или 0x7FFFFFFF). На первый взгляд, получится тоже самое. В чём разница?

V>Сергей, прошу прощения, привет предназначался Славе Антонову получается ( это из-за Re[6]: Не пойму.
Автор: Slava Antonov
Дата: 29.06.04
). Но и тебе привет тоже


Я так и предположил. Но всё равно спасибо
Делай что должно, и будь что будет
Re[5]: Не пойму.
От: Andrew S Россия http://alchemy-lab.com
Дата: 29.06.04 13:11
Оценка: 1 (1)
V>>никто не мешает ошибочно\преднамеренно передать плохой адрес\размер буфера

SH>Угу, значит буферы эти.


V>>MmUserProbeAddress используется еще вот для чего часто:


SH>...


SH>Понятно. Непонятно, почему MmUserProbeAddress нельзя было сделать 0x80000000 (ну или 0x7FFFFFFF). На первый взгляд, получится тоже самое. В чём разница?


Вероятно, все фишка в том, как ProbeForXXX тестирует данные адреса. Насколько я помню, она пробует читать\писать по одному дворду из каждой страницы указанного диапазона. Т.о. MmUserProbeAddress отсекает явные ошибки (грубая проверка) + отсекая при этом попытки залезть в адреса кернела, которые могут в отличие от гвард пространства, быть вполне доступными, а затем при помощи ProbeForXXX кернел окончательно убеждается в валидности предоставленного буфера.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: Не пойму.
От: Slava Antonov Россия http://deadbeef.narod.ru
Дата: 29.06.04 14:46
Оценка:
Hello Andrew S, you wrote:

>>> на самом деле эти предохранительные блоки. Очевидно, любая попытка

>>> записать в адреса выше второго гигабайта из user-mode невозможна
>
> SA>Возмножна, если АП разделено в отношении 3/1, а не 2/2.
> SA>Для этого есть соответсвующий ключ в boot.ini. Также это есть на
> каком-то
> SA>Windows Server
>
> Вот только не надо передергивать

Я не передергиваю, а опровергаю ваше (и те только) утверждение "любая
попытка записать в адреса выше второго гигабайта из user-mode невозможна"

--
Всего хорошего, Слава
http://slava.users.otts.ru
Posted via RSDN NNTP Server 1.9 beta
Re[6]: Не пойму.
От: SergH Россия  
Дата: 29.06.04 16:10
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Вероятно, все фишка в том, как ProbeForXXX тестирует данные адреса. Насколько я помню, она пробует читать\писать по одному дворду из каждой страницы указанного диапазона. Т.о. MmUserProbeAddress отсекает явные ошибки (грубая проверка) + отсекая при этом попытки залезть в адреса кернела, которые могут в отличие от гвард пространства, быть вполне доступными, а затем при помощи ProbeForXXX кернел окончательно убеждается в валидности предоставленного буфера.


Не знаешь — так честно и скажи За ответ опять не катит. Потому как абсолютно непонятно, из-за чего вдруг "грубые ошибки" начинаются не там, где начинается область ядра, а на 64 кб раньше.
Делай что должно, и будь что будет
Re[7]: Не пойму.
От: Andrew S Россия http://alchemy-lab.com
Дата: 29.06.04 16:34
Оценка: 1 (1)
Здравствуйте, SergH, Вы писали:

SH>Здравствуйте, Andrew S, Вы писали:


AS>>Вероятно, все фишка в том, как ProbeForXXX тестирует данные адреса. Насколько я помню, она пробует читать\писать по одному дворду из каждой страницы указанного диапазона. Т.о. MmUserProbeAddress отсекает явные ошибки (грубая проверка) + отсекая при этом попытки залезть в адреса кернела, которые могут в отличие от гвард пространства, быть вполне доступными, а затем при помощи ProbeForXXX кернел окончательно убеждается в валидности предоставленного буфера.


SH>Не знаешь — так честно и скажи За ответ опять не катит.

??? Валерий же уже ответил, я всего лишь сказал другими словами то, о чем он писал.

SH>Потому как абсолютно непонятно, из-за чего вдруг "грубые ошибки" начинаются не там, где начинается область ядра, а на 64 кб раньше.

Не грубые ошибки, а грубая проверка. Разница очевидна?
Гвард страница используется в качестве своеобразного барьера между адресным пространством um\km. Как я понимаю, Ваше недоумение вызвано тем, почему MmUserProbeAddress == km_address_begin — 64кб, а не km_address_begin? Это вполне понятно — потому что адреса, которые выше km_address_begin — 64кб уже по определению не будут валидными для um. Все остальное, что ниже — обязано проверяться при помощи ProbeForXXX, и в случае, если часть буфера попадет на указанные 64 кб, то сгенерится исключения недоступной страницы, т.о. получается, что проверка действительно упрощается. 64кб же, как сказал Валерий:

V>Цифра растет ИМХО из того факта, что гранулярность выделения памяти (see GetSystemInfo) 64Кб — так было задумано для того чтобы быть готовым к поддержке будущих CPU с размером страницы 64Кб. Кстати выравнивание таких регионов также происходит в соотв с гранулярностью выделения памяти, а вот размер адресного пространства кратен уже странице.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: Не пойму.
От: Keith  
Дата: 29.06.04 20:21
Оценка:
SH>>Потому как абсолютно непонятно, из-за чего вдруг "грубые ошибки" начинаются не там, где начинается область ядра, а на 64 кб раньше.
AS>Не грубые ошибки, а грубая проверка. Разница очевидна?
Я особенно еще не разобрался, но так понимаю, что существует два типа проверки на валидность адреса:
1) ошибка вызванная при попадании адреса в блок 64k;
2) ошибка вызванная при попадании адреса в облать ядра.
На сколько я понимаю, первая проверка обходится "дешевле", чем вторая, но я сильно сомневаюсь, что на столько дешевле, чтобы вообще заморачиватся на этот блок в 64k. Короче, есть ли убедительные доказательства тому, что этот блок дает какой-то ощутимый выигрышь?
Кстати, а действия Windows'а при этих двух ошибках разные?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.