Указания к выполнению.
1. Узнаем значения 4 х системных переменных:
2. Чтобы узнать значение переменной MmHighestUserAddress, введите следующую команду:
dd MmHighestUserAddress L1
Команда dd означает отображение 4 байтовых значений, а L1 указывает, что нужно отобразить одно такое значение.
Таким образом, переменная MmHighestUserAddress = 7FFE FFFF.
Заметьте, что верхняя граница пользовательского ВАП не достигает стартового адреса системного ВАП 8000 0000. Область 64 КБ (8000 0000 – 7FFE FFFF = 64 КБ) зарезервирована системой и недоступна пользовательским процессам.
3. Аналогичным образом можно посмотреть значения других системных переменных.
Указания к выполнению.
1. Создайте пустой проект с названием, например, MemoryAlloc, в Visual Studio и добавьте файл исходного кода main.cpp (см. лабораторную работу 2 "Процессы и потоки", задание 3).
Сохраните проект в папке c:\Programs\MemoryAlloc.
2. Вставьте в main.cpp следующий исходный код:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
// Функция пытается записать по адресу lpvPointer 1 байт
VOID WriteCharToMemory(LPVOID lpvPointer, char Symbol)
{
__try
{
*(LPTSTR)lpvPointer = Symbol;
_tprintf ("First byte in memory area = '%c' (hex code = %x)\n\n", Symbol, Symbol);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
_tprintf ("Write to memory area failed\n\n");
}
}
// Вывод сообщения об ошибке
VOID ErrorExit(LPTSTR lpMsg)
{
_tprintf("Error! %s with error code of %ld\n", lpMsg, GetLastError ());
exit (0);
}
VOID _tmain(VOID)
{
LPVOID lpvReserved; // Адрес зарезервированной области памяти
LPVOID lpvCommit; // Адрес переданной области памяти
BOOL bSuccess; // Признак успешного освобождения памяти
SYSTEM_INFO sSysInfo; // Информация о системе
DWORD dwPageSize; // Размер страницы
GetSystemInfo(sSysInfo); // Получаем информацию о системе
_tprintf ("This computer has page size %d\n\n", sSysInfo.dwPageSize);
dwPageSize = sSysInfo.dwPageSize; // Определяем размер страницы
// Точка останова
//_asm int 3
// Резервируем 1 страницу в памяти
lpvReserved = VirtualAlloc(
NULL, // Адрес размещения выбирает система
dwPageSize, // Размер области памяти
MEM_RESERVE, // Резервируем, не передаем
PAGE_READWRITE); // Память доступна для чтения-записи
if (lpvReserved == NULL )
ErrorExit("VirtualAlloc reserve failed");
_tprintf ("Reserve succeeded, address = %x\n\n", lpvReserved);
// Пытаемся записывать в память
WriteCharToMemory(lpvReserved, 'a');
// Точка останова
//_asm int 3
// Передаем зарезервированную страницу
lpvCommit = VirtualAlloc(
lpvReserved, // Адрес зарезервированной области
dwPageSize, // Размер области памяти
MEM_COMMIT, // Передаем память
PAGE_READWRITE); // Память доступна для чтения-записи
if (lpvCommit == NULL )
ErrorExit(TEXT("VirtualAlloc commit failed"));
_tprintf ("Commit succeeded, address = %x\n\n", lpvCommit);
// Пытаемся записывать в память
WriteCharToMemory(lpvCommit, 'a');
// Точка останова
//_asm int 3
// Освобождаем область памяти
bSuccess = VirtualFree(
lpvReserved, // Адрес освобождаемой области
0, // Параметр должен быть равен 0
MEM_RELEASE); // Освобождаем память
if (bSuccess)
_tprintf ("Release succeeded\n\n");
else
_tprintf ("Release failed\n\n");
system("pause");
}
Данная программа сначала резервирует (но не передает) страницу в памяти, пытается записать в эту область данные, затем передает (commit) зарезервированную область и снова пытается записать в неё данные.
3. Установите свойства проекта (см. лабораторную работу 2 "Процессы и потоки", задание 3):
4. Проверьте работоспособность созданного приложения (клавиша F5):
Указания к выполнению.
1. В созданном проекте уберите комментарии (//) перед операторами:
_asm int 3
Требуется убрать 3 комментария (т. е. установить 3 точки останова).
__asm – ключевое слово, которое указывает компилятору, что следующая команда будет командой встроенного Ассемблера.
int 3 – команда Ассемблера, обозначающая точку останова.
2. Запустите проект. Программа должна прерваться в первой точке останова, причем её выполнение можно продолжить, нажав кнопку Продолжить:
Указания к выполнению.
1. Исполняемый файл созданного в предыдущем пункте приложения MemoryAlloc.exe после компиляции проекта должен находиться в следующей папке:
c:\Programs\MemoryAlloc\Release.
Скопируйте исполняемый файл на виртуальную машину.
2. Запустите исполняемый файл. Выполнение программы должно прерываться, а управление перейти к отладчику WinDbg.
3. Установите в отладчике точку останова на функции NtAllocateVirtualMemory. Для этого введите команду:
bp NtAllocateVirtualMemory
Если бы мы не вставили точку останова в само приложение, а до запуска приложения установили бы точку останова на функции NtAllocateVirtualMemory, то было бы трудно отследить запуск этой функции для выделения памяти в приложении, поскольку до этого момента функция NtAllocateVirtualMemory запускается несколько раз (например, для выделения памяти самому приложению).
4. Продолжите выполнение, нажав F5 в отладчике. Должна сработать точка останова на функции NtAllocateVirtualMemory и откроется исходный код этой функции.
Замечание. В отладчике WinDbg номер текущей строки исходного кода отображается в окне отладчика внизу в информационной строке (Ln – Line):
5. Выполните трассировку функции NtAllocateVirtualMemory, обращая внимание на следующие участки кода.
Строка 344 – формирование маски защиты ProtectionMask. В нашем приложении указано значение PAGE_READWRITE = 0*04 (см.
Строка 353 – определение текущего процесса CurrentProcess. Проверьте, что имя исполняемого файла процесса MemoryAlloc.exe (воспользуйтесь окном Locals отладчика, нажав Alt+3; проверьте значение поля ImageFileName переменной CurrentProcess).
Строка 380 – определение размера области памяти (CapturedRegionSize). В нашем случае эта переменная должна быть равна 0x1000 (4096 байт, 1 страница).
Строка 491 – определение величины выравнивания (гранулярности памяти) Alignment. Как указывалось в лекции 8 "Управление памятью", это значение составляет 64 КБ.
Строка 504 – округление размера области памяти CapturedRegionSize до целого числа страниц.
Строка 545 – определение числа страниц NumberOfPages.
Строка 647 – выделение памяти под новый дескриптор виртуального адреса (VAD) при помощи функции ExAllocatePoolWithTag.
Строки 660–668 – заполнение поля VadFlags в дескрипторе виртуального адреса.
Строка 853 – вычисление стартового адреса StartingAddress области памяти при помощи функции MiFindEmptyAddressRange. Эта функция определяет свободные места подходящего размера в памяти, просматривая АВЛ дерево дескрипторов виртуальных адресов.
Строка 867 – вычисление конечного адреса EndingAddress области памяти по простой формуле с округлением до последнего адреса последней страницы, входящей в область.
Строки 899 и 900 – вычисление полей StartingVpn и EndingVpn дескриптора VAD (структура MMVAD) – начального и конечного номеров виртуальных страниц.
Строка 930 – вставка сформированного дескриптора виртуального адреса в АВЛ дерево и его балансировка при помощи функции MiInsertVad.
Строка 1049 – вычисление реального размера зарезервированной области памяти (CapturedRegionSize).
Строка 1050 – увеличение размера виртуальной памяти процесса на величину зарезервированной области (Process->VirtualSize).
Строка 1052 – изменение при необходимости пикового размера виртуальной памяти процесса (Process->PeakVirtualSize).
Строки 1078 и 1079 – возвращение указателя на область памяти (BaseAddress) и реального размера области памяти (RegionSize).
Указания к выполнению.
1. Удалите точку останова с функции NtAllocateVirtualMemory: в меню Edit отладчика выберите Breakpoints… и нажмите кнопку Remove All.
2. Возобновите выполнение виртуальной машины, пройдя все точки останова приложение MemoryAlloc.exe (несколько раз нажмите в отладчике F5).
3. Запустите приложение MemoryAlloc.exe ещё раз.
4. Когда сработает первая точка останова, продолжите в отладчике выполнение (нажмите F5 один раз).
5. На второй точке останова перейдите в окно виртуальной машины и посмотрите, по какому адресу оказалась зарезервирована область памяти:
6. Перейдите в отладчик и просмотрите содержимое памяти по этому адресу, введя команду:
db 340000 L1
Команда db отображает однобайтовое значение, параметр L1 указывает, что необходимо показать одно такое значение.
Как и подсказывает сообщение нашего приложения ("Write to memory area failed"), попытка записи в зарезервированную область память оказалась неудачна, значение в данной ячейке не определено:
Чтобы работать с памятью, её нужно передать (commit).
7. Нажмите в отладчике F5 – программа дойдет до третьей точки останова (после передачи памяти):
Снова просмотрите содержимое памяти по адресу 340000. Сейчас в этой ячейке должен оказаться символ ‘a’ (с шестнадцатеричным кодом 61):
Указания к выполнению.
1. Запустите приложение MemoryAlloc.exe. Когда сработает первая точка останова и управление перейдет к отладчику, требуется узнать адрес процесса MemoryAlloc.exe в памяти. Для этого введите команду:
!process 0 0
и найдите процесс с именем MemoryAlloc.exe:
В данном примере адрес процесса в памяти (адрес объекта EPROCESS): 81F9E320.
2. Определите адрес корня АВЛ дерева дескрипторов виртуальных адресов VadRoot.
Для этого введите команду:
!process 81F9E320 1
Адрес корня VadRoot равен 82251498.
3. Выведите на экран дерево дескрипторов виртуальных адресов процесса MemoryAlloc.exe.
Введите команду:
!vad 82251498
На экран выводится таблица со следующими столбцами:
VAD – адрес дескриптора виртуального адреса – узла дерева;level – уровень в дереве, на котором находится узел;start – номер начальной виртуальной страницы (VPN) в блоке, за который отвечает данный VAD;end – номер последней виртуальной страницы в блоке;commit – счетчик переданных страниц в блоке;После таблицы показывается общее количество узлов в дереве, средний уровень дерева и его максимальная глубина.
4. Продолжите выполнение процесса MemoryAlloc.exe, нажав F5 в отладчике. Должна сработать вторая точка останова.
Снова выведите на экран дерево дескрипторов виртуальных адресов:
Вы должны заметить, что общее количество дескрипторов увеличилось на единицу, т. е. после резервирования области памяти в приложении в дереве появился новый дескриптор по адресу 81F454E8.
Обратите внимание на номер стартовой виртуальной страницы для этого дескриптора: 340. Сравните это значение с адресом зарезервированной области памяти в приложении:
Как и отмечалось в лекции 8 "Управление памятью" номер виртуальной страницы в VAD получается путем отбрасыванием младших 12 бит (или 3 шестнадцатеричных цифр).
5. Продолжите выполнение приложения (F5). Сработает третья точка останова.
Снова выведите дерево дескрипторов виртуальных адресов: на экран:
Обратите внимание, что после передачи (commit) зарезервированной области памяти счетчик переданных страниц нового дескриптора увеличился на единицу.
Задание 1. Исследуйте действие различных значений параметров защиты памяти функции VirtualAlloc на примере приложения MemoryAlloc.
Указания к выполнению.
Желательно также исследовать влияние параметра защиты на дескрипторы виртуальных адресов VAD.
Задание 2. Продолжить исследование функции NtAllocateVirtualMemory.
Указания к выполнению.
1. В основной части лабораторной работы (задание 4) осуществлялась трассировка функции NtAllocateVirtualMemory при резервировании области памяти в приложении MemoryAlloc.
Выполните трассировку данной функции при передаче (commit) области памяти (поставьте точку останова на функции NtAllocateVirtualMemory после срабатывания второй точки останова в программе MemoryAlloc.
Задание 3. Исследовать процесс трансляции виртуальных адресов.
Указания к выполнению.
1. Выполните процесс трансляции виртуального адреса из диапазона адресов области памяти, выделенной в приложении MemoryAlloc. Воспользуйтесь описанием трансляции из лекции 8 "Управление памятью" и примером из [5, стр. 456].
Задание 4. Исследовать утилиту для работы с виртуальной памятью VMMap от Sysinternals.
Указания к выполнению.
1. Скачайте утилиту VMMap по адресу:
http://technet.microsoft.com/en-us/sysinternals/dd535533
2. Исследуйте возможности утилиты на примере приложения MemoryAlloc.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.