6. Управление памятью в Windows

Управление памятью в Windows

Введение

В этом модуле рассматриваются основы управления памятью в Windows. Понимание того, как Windows обрабатывает память, является ключевым для создания сложных вредоносных программ.

Виртуальная память и страничное управление

В современных операционных системах память не отображается напрямую на физическую память (т.е. ОЗУ). Вместо этого процессы используют виртуальные адреса памяти, которые отображаются на физические адреса памяти. Есть несколько причин для этого, но в конечном счете целью является экономия физической памяти. Виртуальная память может отображаться на физическую память, а также может быть сохранена на диске. Благодаря использованию виртуальной адресации памяти становится возможным совместное использование одного и того же физического адреса разными процессами с помощью уникального виртуального адреса памяти. Виртуальная память основывается на концепции страничного управления памятью, которое разделяет память на фрагменты размером 4 Кб, называемые "страницами".

На изображении ниже из книги Windows Internals 7-е издание - часть 1.

Состояние страницы

Страницы, находящиеся в виртуальном адресном пространстве процесса, могут находиться в одном из трех состояний:

  1. Свободное - Страница не выделена и не зарезервирована. Страница недоступна для процесса. Она доступна для резервирования, выделения или одновременного резервирования и выделения. Попытка чтения или записи в свободную страницу может привести к исключительной ситуации нарушения доступа.
  1. Зарезервированное - Страница зарезервирована для будущего использования. Диапазон адресов не может быть использован другими функциями выделения. Страница недоступна и с ней не связано физическое хранилище. Она доступна для выделения.
  1. Выделенное - Выделена память из общего объема ОЗУ и файла подкачки на диске. Страница доступна, а доступ контролируется одной из констант защиты памяти. Система инициализирует и загружает каждую выделенную страницу в физическую память только при первой попытке чтения или записи в эту страницу. При завершении процесса система освобождает память для выделенных страниц.

Параметры защиты страницы

После выделения страницы необходимо установить ее параметры защиты. Список констант защиты памяти можно найти здесь, но ниже приведены некоторые примеры.

Защита памяти

Современные операционные системы обычно имеют встроенные механизмы защиты памяти для предотвращения эксплойтов и атак. Эти механизмы также важны для учета при создании или отладке вредоносных программ.

Пространство памяти x86 против x64

При работе с процессами Windows важно знать, является ли процесс x86 или x64. В x86 процессах размер доступной памяти составляет 4 ГБ (0xFFFFFFFF), в то время как в x64 доступно гораздо больше памяти - 128 ТБ (0xFFFFFFFFFFFFFFFF).

Пример выделения памяти

В этом примере рассматриваются небольшие фрагменты кода, чтобы лучше понять, как можно взаимодействовать с памятью Windows с помощью функций на языке C и API Windows. Первый шаг в работе с памятью - это выделение памяти. Приведенный ниже фрагмент демонстрирует несколько способов выделения памяти, что фактически означает резервирование памяти в работающем процессе.

// Выделение буфера памяти размером *100* байт

// Метод 1 - С использованием malloc()
PVOID pAddress = malloc(100);

// Метод 2 - С использованием HeapAlloc()
PVOID pAddress = HeapAlloc(GetProcessHeap(), 0, 100);

// Метод 3 - С использованием LocalAlloc()
PVOID pAddress = LocalAlloc(LPTR, 100);

Функции выделения памяти возвращают базовый адрес, который представляет собой указатель на начало выделенного блока памяти. Используя приведенные выше фрагменты, pAddress будет базовым адресом выделенного блока памяти. Используя этот указатель, можно выполнять различные действия, такие как чтение, запись и выполнение. Возможные действия зависят от параметров защиты, присвоенных выделенному региону памяти.

На рисунке ниже показано, как выглядит pAddress в отладчике.

При выделении памяти она может быть пустой или содержать случайные данные. Некоторые функции выделения памяти предоставляют опцию обнуления региона памяти во время процесса выделения.

Пример записи в память

Следующий шаг после выделения памяти - обычно запись в этот буфер. Для записи в память можно использовать несколько вариантов, но для этого примера используется функция memcpy.

PVOID pAddress	= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);

CHAR* cString	= "MalDev Academy Is The Best";

memcpy(pAddress, cString, strlen(cString));

HeapAlloc использует флаг HEAP_ZERO_MEMORY, который приводит к инициализации выделенной памяти нулевыми значениями. Затем строка копируется в выделенную память с помощью функции memcpy. Последний параметр в memcpy - это количество байтов для копирования. Затем проверяется буфер, чтобы убедиться, что данные были успешно записаны.

Освобождение выделенной памяти

Когда приложение заканчивает использовать выделенный буфер, рекомендуется освободить его или освободить память, чтобы избежать утечки памяти.

В зависимости от того, какая функция была использована для выделения памяти, будет соответствующая функция для освобождения памяти. Например:

HeapFree(GetProcessHeap(), 0, pAddress);

Функция HeapFree освобождает ранее выделенный блок памяти. Первый параметр - дескриптор кучи или базовый адрес кучи. Второй параметр - опции, указывающие на дополнительные действия при освобождении памяти. Третий параметр - указатель на блок памяти, который нужно освободить.

Обратите внимание, что при освобождении памяти она не стирается или очищается. Просто помечается как доступная для повторного использования операционной системой.

Выводы

Управление памятью в Windows является важным аспектом разработки программ и понимания безопасности операционной системы. Правильное выделение, запись и освобождение памяти не только помогают создавать эффективные и надежные программы, но и предотвращают различные виды атак на память.

Рекомендуется ознакомиться с документацией Microsoft и другими ресурсами, чтобы получить более подробную информацию о управлении памятью в Windows и использовании соответствующих функций и API.

Источник: https://maldevacademy.com/modules/6