Информация об изменениях

Сообщение Re: Мультипроцессный защищенный код от 05.04.2018 17:08

Изменено 05.04.2018 17:10 ononim

Re: Мультипроцессный защищенный код
Как уже писали, главная проблема — получить фиксированный между разными процессами адрес, чтоб не занят был. В принципе если говорить про драйвер, то это несложно сделать из нотификации на создание процесса резервировать регион памяти по заданному адресу и радоваться жизни. Вопрос какой адрес выбрать для фиксации, а выбрать надо такой, чтоб не перекрывался с адресом загрузки базовых длл (ntdll/kernelbae/kernel32/user32/gdi32/может-там-еще-чего-добавили) в данной сессии и не перекрывался с адресом загрузки ваших ехе модулей.
Предполагаемый функционал в драйвере:
— Драйвер имеет admin-only IOCTL, который ему говорит: для процессов, созданных из имажа с таким то путем резервируй адреса с такогото по такой-то.

Предполагаемый функционал в юзермодном 'главном' сервисе:
— При запуске определяет текущие ASLR-ed базы указанных выше длл, ехе-шника нужного имажа/ов, подбирает заданный адрес и дергает драйвер за тот самый IOCTL.
— Имеет локальный IPC, через пайпы например или LPC, который позволяет дернуть его из непривелигированного процесса, запросив shared memory. При дерганье сервис создает персональнй mapping, занимающий некоторый заданный диапазон адресов зарезервированного пула между собой и процессом клиентом. MapViewOfFile2 позволяет промапить неименованный анонимный мапинг в АП чужого процесса. Ну или NtMapViewOfSection, если вы без комплексов.
— При желании на эту область памяти можно даже натянуть хип.
— Помимо мапинга вам еще понадобится некая синхронизация клиент-сервер.

Очевидные недостатки — область памяти будет иметь захардкоженный размер на всех и еще меньший размер на одного клиента. В принципе, на х64 этот размер может быть достаточно велик для любых применений, главное — не комтить страницы сразу, а максимально пользоваться MEM_RESERVE/SEC_RESERVE.

В итоге получится не требующий фиксапов межпроцессный хип.

  Скрытый текст
Но это все равно глупая затея. И дело не в трудоемкости. Защищенность сервиса предполагает, что клиент не сможет его порушить. А значит, что сервису придется тщательно смотреть за структурами данных, которые ему в расшаренную память положил процесс. Причем это значит, что клиент, будучи написанным хакером, может abuse-ить ваш протокол, к примеру записывая в расшаренную память в обход предусмотренного механизма синхронизации. Это не то чтобы нерешаемая задача — можно обеспечить транзакционную синхронизацию, переключающую режим работы хипа между клиентом и сервисов устанавливая защиту на страницы памяти которую клиент не сможет изменить, но по итогу с такой синхронизацией + проверками валидности данных работать оно врядл будет быстрее чем реализация протокола-через-пайпы. А без них — ни о какой защищенности кода говорить нельзя.
Re: Мультипроцессный защищенный код
Как уже писали, главная проблема — получить фиксированный между разными процессами адрес, чтоб не занят был. В принципе если говорить про драйвер, то это несложно сделать из нотификации на создание процесса резервировать регион памяти по заданному адресу и радоваться жизни. Вопрос какой адрес выбрать для фиксации, а выбрать надо такой, чтоб не перекрывался с адресом загрузки базовых длл (ntdll/kernelbase/kernel32/user32/gdi32/может-там-еще-чего-добавили) в данной сессии и не перекрывался с адресом загрузки ваших ехе модулей.
Предполагаемый функционал в драйвере:
— Драйвер имеет admin-only IOCTL, который ему говорит: для процессов, созданных из имажа с таким то путем резервируй адреса с такогото по такой-то.

Предполагаемый функционал в юзермодном 'главном' сервисе:
— При запуске определяет текущие ASLR-ed базы указанных выше длл, ехе-шника нужного имажа/ов, подбирает заданный адрес и дергает драйвер за тот самый IOCTL.
— Имеет локальный IPC, через пайпы например или LPC, который позволяет дернуть его из непривелигированного процесса, запросив shared memory. При дерганье сервис создает персональнй mapping, занимающий некоторый заданный диапазон адресов зарезервированного пула между собой и процессом клиентом. MapViewOfFile2 позволяет промапить неименованный анонимный мапинг в АП чужого процесса. Ну или NtMapViewOfSection, если вы без комплексов.
— При желании на эту область памяти можно даже натянуть хип.
— Помимо мапинга вам еще понадобится некая синхронизация клиент-сервер.

Очевидные недостатки — область памяти будет иметь захардкоженный размер на всех и еще меньший размер на одного клиента. В принципе, на х64 этот размер может быть достаточно велик для любых применений, главное — не комтить страницы сразу, а максимально пользоваться MEM_RESERVE/SEC_RESERVE.

В итоге получится не требующий фиксапов межпроцессный хип.

  Скрытый текст
Но это все равно глупая затея. И дело не в трудоемкости. Защищенность сервиса предполагает, что клиент не сможет его порушить. А значит, что сервису придется тщательно смотреть за структурами данных, которые ему в расшаренную память положил процесс. Причем это значит, что клиент, будучи написанным хакером, может abuse-ить ваш протокол, к примеру записывая в расшаренную память в обход предусмотренного механизма синхронизации. Это не то чтобы нерешаемая задача — можно обеспечить транзакционную синхронизацию, переключающую режим работы хипа между клиентом и сервисов устанавливая защиту на страницы памяти которую клиент не сможет изменить, но по итогу с такой синхронизацией + проверками валидности данных работать оно врядл будет быстрее чем реализация протокола-через-пайпы. А без них — ни о какой защищенности кода говорить нельзя и проще заюзать предложенный выше буст.