Модератор: Brickgroup
При написании Waiter'а я прекрасно помнил о DEP, которая, если включена в Windows, не даст выполнить код, сгенерированный в памяти, если на этой памяти нет флага, разрешающего выполнение кода. В моём MSDN говорилось, что функция GlobalAlloc отводит память уже с этим флагом, и особо подчёркивалось, что для выполнения сгенерированного в ней кода больше ничего не нужно.
Однако, тестирование Waiter'а на компьютере с аппаратной поддержкой DEP показало, что он вылетает с исключением защиты памяти. В онлайновом же MSDN к тому моменту всё уже было подправлено: для функции GlobalAlloc уже говорилось, что никаких исполняемых флагов она не ставит, и что для выполнения сгенерированного кода надо самому ставить нужный флаг защиты через VirtualProtect.
Посему, Waiter был немного переписан в части отведения памяти, однако, остался один нюанс.
Если использовать VirtualAlloc для изначального выделения памяти, то с безопасностью всё в порядке, однако отводится целая страница памяти (у меня, например, это 4 Кб), что гораздо больше, чем нужно. Хотя, один экземпляр Waiter'а коммиттит целый мегабайт памяти в качестве стека для нового потока (если, конечно, вы не подправили PE-заголовок файла), так что на этом фоне 4 дополнительных Кб выглядят ничтожно.
Если же использовать GlobalAlloc с последующим VirtualProtect, то память будет расходоваться более эффективно, т.к. GlobalAlloc сохраняет определённую информацию между вызовами себя, и потому выделяет следующий кусок из той же страницы, что и предыдущий, но в этом случае может возникнуть та ситуация, что я своим VirtualProtect сниму нужный флаг защиты со страницы памяти, которая была отведена при помощи GlobalAlloc родительским приложением, в котором находится Waiter. Хотя, вред от этого увидеть весьма трудно, поскольку устанавливаемый мною режим доступа самый широкий, без ограничений, а режимы copy-on-write для памяти, отведённой через GlobalAlloc, недоступны.
Поэтому! Способ отведения памяти регулируется через условную компиляцию.
По умолчанию выбран безусловно безопасный вариант, с VirtualAlloc.
Кому надо, включайте обратно GlobalAlloc. Константа вот:
#Const USE_VIRTUAL_ALLOC = True
tyomitch писал(а):Опечатка?
tyomitch писал(а):У всех остальных так же.
Описание GlobalAlloc писал(а):
...
All memory is created with execute access; no special function is required to execute dynamically generated code.
...
sombody писал(а):Учитывая, что где-то написано, что в какой-то из осей права на выполнение только из VirtualAlloc.
Короче, там где работает DEP не получится выставить право на исполнение через VirtualProtect. Тока из VirtualAlloc
Хакер писал(а):Описание GlobalAlloc писал(а):All memory is created with execute access; no special function is required to execute dynamically generated code.
Подлинное описание GlobalAlloc писал(а):To execute dynamically generated code, use the VirtualAlloc function to allocate memory and the VirtualProtect function to grant PAGE_EXECUTE access.
Хакер писал(а):Правда?
typedef void myproc();
int main(int argc, char* argv[])
{
myproc* p = (myproc*)GlobalAlloc(GPTR,100);
*((char*)p)=0xC3;
p();
return 0;
}
The instruction at "0x00155700" referenced memory at "0x00155700". The memory could not be "written".
В моём MSDN говорилось, что функция GlobalAlloc отводит память уже с этим флагом, и особо подчёркивалось, что для выполнения сгенерированного в ней кода больше ничего не нужно.
.somebody писал(а):в какой-то из осей права на выполнение только из VirtualAlloc.
Короче, там где работает DEP не получится выставить право на исполнение через VirtualProtect. Тока из VirtualAlloc
typedef void myproc();
int main(int argc, char* argv[])
{
myproc* p = (myproc*)GlobalAlloc(GPTR,100);
printf("%d\n", VirtualProtect(p, 100, PAGE_EXECUTE_READWRITE, NULL));
printf("%d\n", GetLastError());
return 0;
}
0
998
Эмм, а чем не устраивает куча windows с HEAP_CREATE_ENABLE_EXECUTE?Хакер писал(а):Выход: можно резервировать и коммитить для них страницы памяти, самому следить когда коммитить новую страницу под функции, самому дефрагментировать страницы (да - ведь процедурки будут и удаляться, причём в абсолютно хаотичном порядке).
Никаких проблем нет, разве что реализовывать менеждер памяти для всего этого дела - влом и некогда.
Второй вариант: переложить всё это на плечи ОС. И размещать процедурки скажем в куче (а почему бы и нет?). Но у кучи изначально нет execute-права. Значит надо сделать страницы кучи исполнимыми с помощью VirtualProtect (а почем бы и нет?). Но если в какой-то системе попытка "grant PAGE_EXECUTE access" с помощью VirtualProtect обломится (об этом ведь говорил somebody), то я вынужден юзать первый вариант (т.е. управлять памятью самостоятельно).
Хакер писал(а):И да, - чем она GSerg-а не устраивает?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13