Информация о процессе в livekd: 2338
Информация о VAD(virtual addres descriptor) приложения OS4.exe до вызова какой-либо функции:
Зарезервируем место в памяти (10 байт) в автоматическом режиме и посмотрим на изменения информации в VAD-Root.
Количество VADs увеличилось на 1. Появился виртуальный адресный дескриптор с характеристикой start = 7B0. Адрес, возвращаемый в программе при запросе резервирования памяти равен 7B0000. Commit = 1, что отражает количество предоставленных программе страниц виртуальной памяти.
Теперь зарезервируем 10 байт по адресу 0х12121515 в ручном режиме.
Появился ещё один VAD с характеристикой start 12100 и end 12121.
0x12120000 - 0x12121000 = 0x1000 = 4096 байт. Таким образом были зарезервирована 1 страница. Commit все также равен 1.
Попробуем зарезервировать больше памяти (17000 байт) по адресу 0х00030000
Количество VADs увеличилось на 1. Теперь Commit = 5 (5*4096 =20480), чего как раз хватает для использования 17000 байт.
Запишем число 451 в память по адресу 0х00030000
По сравнению с предыдущим скриншотом ничего не изменилось. Прочитаем содержимое ячеек памяти с базовым адресом 0x00030000
Число = показывает, что с помощью функции WriteProcessMemory данные были успешно записаны по адресу 0х00030000.
Теперь изменим protection option страницы по адресу 0x00030000 на NOACCESS
Отображение информации в VAD root о дескрипторе с полем start равном 30 не изменилось (READWRITE), возможно поле, отображающее атрибуты защиты, хранит атрибут защиты памяти при её инициализации, то есть только начальный.
Теперь освободим память, которую мы зарезервировали в процессе выполнения работы, а именно память по адресам: 0x12121515, 0x007B0000, 0x00030000:
Как видно количество VADs изменилось, пропали 3 дескриптора отвечающие за 3 адреса, по которым мы ранее зарезервировали память.
Вывод: в ОС windows 10 резервируемое количество памяти всегда кратно полю с dwAllocationGranularity структуры _SYSTEM_INFO, которое в моем случае оказалось равно = байт. При резервировании памяти, вводя начальный адрес ос выделяет регион страниц длиной кратной 32768 байт. Поле dwPageSize равное в моем случае 4096 байт = 0x1000 определяет размер страницы, то есть минимально выделяемое операционной системой количество памяти пользовательским процессам, так же это минимально адресуемое количество памяти для установления атрибутов защиты и освобождения памяти. Размер региона в байтах на скриншотах в лабораторной работе отражает размер подряд идущих страниц с одинаковыми значениями атрибутов.
Задание 4.3. Использование проецируемых файлов для обмена данными между процессами.
Информация о VAD root каждого из процессов до вызова каких-либо функций:
reader.exe
writer.exe
Откроем дескриптор файла размером 55 байт и создадим объект в программе writer.exe
Cпроецируем фрагмент в 13 байт файла file.txt размером 55 байт на ОЗУ
Количество VADs увеличилось на 1. Появился новый VAD с характеристикой mapped.
Введем 333 в спроецированный на ОЗУ файл:
Данные успешно записаны.
Теперь откроем существующий объект в reader.exe
Спроецируем фрагмент файла:
Количество VADs увеличилось на 1. Появился новый VAD с характеристикой mapped.
Просмотрим содержимое памяти отображенного на ОЗУ файла file.txt
Просмотрим содержимое памяти с помощью livekd:
Мы можем наблюдать, что читатель видит тот же файл, что создал писатель, т.к. текст совпадает. А также, что обе программы имеют доступ к данному файлу.
Вывод: с помощью WinApi можно выполнить проецирование файлов на ОЗУ. Проецирование файлов — это ассоциация содержимого файла с некоторой областью виртуального адресного пространства процесса. Проецируемые файлы позволяют резервировать регион адресного пространства и передавать ему физическую память, которая не выделяется из страничного файла, а берется из файла, уже находящегося на диске. Как только файл спроецирован в память, к нему можно обращаться так, будто он целиком в нее загружен. Это позволяет обойтись без операций файлового ввода-вывода и буферизации его содержимого, а также разделить данные между несколькими процессами, выполняемыми на одной машине.
#include <iostream>
#include "VM.h"
using namespace std;
int menu();
int main() {
setlocale(0, ".1251");
int notExit;
do {
switch (notExit = menu())
{
case 1:
systemInfo();
break;
case 2:
virtualMemoryStatus();
break;
case 3:
virtualPageStatus(0);
break;
case 4:
separateReserveCommit();
break;
case 5:
simultaneousReserveCommit();
break;
case 6:
writeData();
break;
case 7:
protectVirtualPage();
break;
case 8:
freeVirtualPage(0);
break;
case 0:
break;
default:
if (notExit)
cout << "Error" << endl;
}
if (notExit)
system("pause");
} while (notExit);
return 0;
}
int menu()
{
system("cls");
int point;
do {
cin.clear();
cin.sync();
cout << "Select menu item" << endl;
cout << "1 - About system" << endl;
cout << "2 - Memory status" << endl;
cout << "3 - State of the virtual memory area" << endl;
cout << "4 - Separate region redundancy and physical memory transfer" << endl;
cout << "5 - Simultaneous reservation of a region and transfer of physical memory" << endl;
cout << "6 - Write data" << endl;
cout << "7 - Memory region access protection" << endl;
cout << "8 - Clear memory" << endl;
cout << "0 - Exit" << endl;
cout << "> ";
cin >> point;
if (cin.fail())
cout << "Error" << endl;
} while (cin.fail());
system("cls");
return point;
}
#include "VM.h"
using namespace std;
void systemInfo() {
_SYSTEM_INFO systemInfo;
//GetSystemInfo(&systemInfo); // GetSystemInfo
GetNativeSystemInfo(&systemInfo);
cout << "About system:" << endl;
cout << "Architecture: ";
switch (systemInfo.wProcessorArchitecture)
{
case 5:
cout << "ARM" << endl;
break;
case 6:
cout << "Intel Itanium-based" << endl;
break;
case PROCESSOR_ARCHITECTURE_AMD64:
cout << "x64 (AMD or Intel)" << endl;
break;
case PROCESSOR_ARCHITECTURE_INTEL:
cout << "Intel x86" << endl;
break;
default:
cout << "Non" << endl;
break;
}
cout << "Cores: " << systemInfo.dwNumberOfProcessors << endl;
cout << "Type of proc: ";
switch (systemInfo.dwProcessorType)
{
case 386:
cout << "Intel 386" << endl;
break;
case 486:
cout << "Intel 486" << endl;
break;
case 586:
cout << "Intel Pentium" << endl;
break;
case 2200:
cout << "Intel IA64" << endl;
break;
case 8664:
cout << "AMD x8664" << endl;
break;
default:
cout << "ARM" << endl;
break;
}
cout << "Proc level (CPU vendor): " << systemInfo.wProcessorLevel << endl;
cout << "Page size: " << systemInfo.dwPageSize << endl;
cout << "Min address for app: " << systemInfo.lpMinimumApplicationAddress << endl;
cout << "Max address for app: " << systemInfo.lpMaximumApplicationAddress << endl;
bitset<8> x(systemInfo.dwActiveProcessorMask);
cout << "Active cores: " << x << endl;
}
void virtualMemoryStatus() {
const int divider = 1024;
const int width = 12;
MEMORYSTATUSEX memoryStatusEx;
memoryStatusEx.dwLength = sizeof(memoryStatusEx);
GlobalMemoryStatusEx(&memoryStatusEx); // GlobalMemoryStatus
cout.width(width - 1);
cout << memoryStatusEx.dwMemoryLoad << "% in use\n";
cout.width(width);
cout << memoryStatusEx.ullTotalPhys / divider << " total Kb memory\n";
cout.width(width);
cout << memoryStatusEx.ullAvailPhys / divider << " available Kb memory\n";
cout.width(width);
cout << memoryStatusEx.ullTotalPageFile / divider << " total Kb paged file\n";
cout.width(width);
cout << memoryStatusEx.ullAvailPageFile / divider << " available Kb paged file\n";
cout.width(width);
cout << memoryStatusEx.ullTotalVirtual / divider << " total Kb virtual memory\n";
cout.width(width);
cout << memoryStatusEx.ullAvailVirtual / divider << " available Kb virtual memory\n";
cout.width(width);
cout << memoryStatusEx.ullAvailExtendedVirtual / divider << " availabe Kb extended memory\n";
}
void virtualPageStatus(DWORD address) {
MEMORY_BASIC_INFORMATION memoryInfo;
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
if (!address) {
cout << "Enter an address in the range of 0x" << systemInfo.lpMinimumApplicationAddress
<< " before 0x" << systemInfo.lpMaximumApplicationAddress << "): 0x";
cin >> hex >> address;
}
VirtualQuery((LPCVOID)address, &memoryInfo, sizeof(memoryInfo));
cout << "Base address: 0x" << memoryInfo.BaseAddress << endl;
cout << "Base address of allocated memory: 0x" << memoryInfo.AllocationBase << endl;
cout << "Region size: " << memoryInfo.RegionSize << endl;
cout << "Access mode: 0x" << hex << memoryInfo.Protect << endl;
if (memoryInfo.Protect & PAGE_NOACCESS) cout << " PAGE_NOACCESS" << endl;
if (memoryInfo.Protect & PAGE_READONLY) cout << " PAGE_READONLY" << endl;
if (memoryInfo.Protect & PAGE_READWRITE) cout << " PAGE_READWRITE" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE_WRITECOPY) cout << " PAGE_EXECUTE_WRITECOPY" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE) cout << " PAGE_EXECUTE" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE_READ) cout << " PAGE_EXECUTE_READ" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE_READ) cout << " PAGE_EXECUTE_READ" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE_READWRITE) cout << " PAGE_EXECUTE_READWRITE" << endl;
if (memoryInfo.Protect & PAGE_EXECUTE_WRITECOPY) cout << " PAGE_EXECUTE_WRITECOPY" << endl;
if (memoryInfo.Protect & PAGE_GUARD) cout << " PAGE_GUARD" << endl;
if (memoryInfo.Protect & PAGE_NOCACHE) cout << " PAGE_NOCACHE" << endl;
if (memoryInfo.Protect & PAGE_WRITECOMBINE) cout << " PAGE_WRITECOMBINE" << endl;
cout << "Page status: 0x" << hex << memoryInfo.State << endl;
if (memoryInfo.State & MEM_COMMIT) cout << " MEM_COMMIT" << endl;
if (memoryInfo.State & MEM_FREE) cout << " MEM_FREE" << endl;
if (memoryInfo.State & MEM_RESERVE) cout << " MEM_RESERVE" << endl;
cout << "Page type: 0x" << hex << memoryInfo.Type << endl;
if (memoryInfo.Type & MEM_IMAGE) cout << " MEM_IMAGE" << endl;
if (memoryInfo.Type & MEM_MAPPED) cout << " MEM_MAPPED" << endl;
if (memoryInfo.Type & MEM_PRIVATE) cout << " MEM_PRIVATE" << endl;
cout << dec;
}
void separateReserveCommit() {
PVOID pMemory = 0;
PVOID pBaseAddress = 0;
DWORD dwSize = 0;
cout << "Base address (0 to automatically set the address by the system): 0x";
cin >> hex >> pBaseAddress;
cout << "Size (in bytes): ";
cin >> dec >> dwSize;
pMemory = VirtualAlloc(pBaseAddress, dwSize, MEM_RESERVE, PAGE_READWRITE);
if (pMemory != NULL) {
cout << "\n\nMemory reserved: \n";
virtualPageStatus((DWORD)pMemory);
}
else {
cout << "Failed to allocate memory!" << endl;
return;
}
pMemory = VirtualAlloc(pMemory, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (pMemory != NULL) {
cout << "\n\nMemory used:\n";
virtualPageStatus((DWORD)pMemory);
}
else {
cout << "Failed to allocate memory!" << endl;
return;
}
}
void simultaneousReserveCommit() {
PVOID pMemory = 0;
PVOID pBaseAddress = 0;
DWORD dwSize = 0;
cout << "Base address (0 to automatically set the address by the system): 0x";
cin >> hex >> pBaseAddress;
cout << "Размер (в байтах): ";
cin >> dec >> dwSize;
pMemory = VirtualAlloc(pBaseAddress, dwSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pMemory != NULL) {
cout << "\n\nMemory allocated: \n";
virtualPageStatus((DWORD)pMemory);
}
else {
cout << "Failed to allocate memory!" << endl;
return;
}
}
void writeData() {
PVOID pMemory = 0;
PVOID pBaseAddress = 0;
DWORD dwSize = 0;
int data = 0;
cout << "Base address (0 to automatically set the address by the system): 0x";
cin >> hex >> pBaseAddress;
MEMORY_BASIC_INFORMATION memoryInfo;
VirtualQuery((LPCVOID)pBaseAddress, &memoryInfo, sizeof(memoryInfo));
if (memoryInfo.Protect & PAGE_NOACCESS) {
cout << "Memory is protected" << endl;
return;
}
cout << "Data: ";
cin >> dec >> data;
if (pBaseAddress) {
memcpy(pBaseAddress, &data, sizeof(int));
cout << "Memory reading (0x" << hex << pBaseAddress << dec << "): " << (*(PDWORD)pBaseAddress) << endl;
}
else {
pMemory = VirtualAlloc(pBaseAddress, sizeof(int), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
memcpy(pMemory, &data, sizeof(int));
cout << "Memory reading (0x" << hex << pMemory << dec << "): " << (*(PDWORD)pMemory) << endl;
}
}
void protectVirtualPage() {
PVOID pMemory = 0;
PVOID pBaseAddress = 0;
DWORD dwSize = 0;
cout << "Base address (0 to automatically set the address by the system): 0x";
cin >> hex >> pBaseAddress;
if (pBaseAddress) {
DWORD flOldProtect = 0;
VirtualProtect(pBaseAddress, sizeof(int), PAGE_NOACCESS, &flOldProtect);
cout << "\n\nMemory is protected: \n";
virtualPageStatus((DWORD)pBaseAddress);
}
else {
pMemory = VirtualAlloc(pBaseAddress, sizeof(int), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pMemory != NULL) {
cout << "\n\nMemory allocated: \n";
virtualPageStatus((DWORD)pMemory);
}
DWORD flOldProtect = 0;
VirtualProtect(pMemory, sizeof(int), PAGE_NOACCESS, &flOldProtect);
cout << "\n\nMemory is protected: \n";
virtualPageStatus((DWORD)pMemory);
VirtualFree(pMemory, 0, MEM_RELEASE);
}
}
void freeVirtualPage(DWORD address) {
PVOID pMemory = 0;
if (!address) {
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
cout << "Enter an address in the range of 0x" << systemInfo.lpMinimumApplicationAddress
<< " before 0x" << systemInfo.lpMaximumApplicationAddress << "): 0x";
cin >> hex >> address;
}
VirtualFree((LPVOID)address, 0, MEM_RELEASE);
cout << "\n\nMemory cleared: \n";
virtualPageStatus((DWORD)address);
}
#pragma once
#define WINVER 0x0500
#include <iostream>
#include <windows.h>
#include <winbase.h>
#include <io.h>
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <bitset>
void systemInfo();
void virtualMemoryStatus();
void virtualPageStatus(DWORD address);
void separateReserveCommit();
void simultaneousReserveCommit();
void writeData();
void protectVirtualPage();
void freeVirtualPage(DWORD address);
#include <iostream>
#include <windows.h>
#include <stdio.h>
using namespace std;
int main()
{
setlocale(0, ".1251");
HANDLE hFile;
HANDLE hMapFile;
LPVOID lpMapAddress;
LPCSTR filename = "file.txt";
char data[1024];
DWORD fSize;
DWORD bytesToMap;
system("pause");
cout << "Create file" << endl;
hFile = CreateFileA(filename, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
cout << "File file.txt created successfully" << endl;
else
cout << "Error! The file was not created." << endl;
cout << "Size of file: ";
cin >> fSize;
hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, fSize, "mapFile");
if (hMapFile != INVALID_HANDLE_VALUE)
cout << "Object mapping created" << endl;
else
cout << "Error! The object mapping was not created." << endl;
system("pause");
cout << "Projecting file in memory" << endl;
cout << "Enter the number of bytes.: ";
cin >> bytesToMap;
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, bytesToMap);
cout << "Projecting completed" << endl;
system("pause");
cout << "Recording data to file" << endl;
cout << "Enter data: ";
cin >> data;
memcpy(lpMapAddress, data, strlen(data));
cout << "Projection Address: " << lpMapAddress << endl;
system("pause");
UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
CloseHandle(hFile);
return 0;
}
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
setlocale(0, ".1251");
HANDLE hMapFile;
PVOID lpMapAddress;
char data[1024];
system("pause");
cout << "Opening file" << endl;
hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "mapFile");
if (hMapFile != INVALID_HANDLE_VALUE)
cout << "The projected file is open.\n";
else
cout << "Error! The projected file was not open\n";
system("pause");
cout << "Projection of memory file fragment" << endl;
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpMapAddress == 0) {
cerr << "Unable to open file projection\n";
system("pause");
return 1;
}
else
cout << "Projection is complete." << endl;
system("pause");
cout << "Read file" << endl;
memcpy(data, (char*)lpMapAddress, 1024);
cout << "Data at address " << lpMapAddress << ": " << data << endl;
system("pause");
UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
return 0;
}