Module Stomping
Load a PICO over a stomped module.
Project Files
Notes
This is a simple module stomping PICO runner. It's main purpose is to show stomping .pdata with Crystal Palace's generated stack unwind data.
loader.c loads xpsservices.dll, finds .text and places our PICO's code over it. It places our PICO's constants and data over the module's .data section. And, our stack unwinding meta-information is placed over .pdata (x64 only). The result is our PICO lives in image memory and has unwindable call stacks.
Now, for some unwinding-specific details:
.pdata is a block of RUNTIME_FUNCTION values. These point to the begin and end offset of non-leaf functions relative to a base address. Crystal Palace generates this data assuming position 0 of our executable code is the base. But, in a stomped module, the base of the module is the base address. In a stomping context, we have to play nice with the module's base, because this and the size of .pdata are cached elsewhere.
Another important detail relates to how .pdata is searched. Windows does a binary search on this information. So, when we stomp .pdata, we need to take care that our code is findable in a binary search context. Here, I've simplified things, because I've placed our RUNTIME_INFORMATION block over position 0. I'm taking a chance that our RUNTIME_INFORMATION is sorted properly over the existing .pdata. A more robust implementation might walk each existing RUNTIME_INFORMATION block, find where the new one best fits, and overwrite the old one.
Another detail relates to alignment of .xdata. Crystal Palace packages unwind codes, which describe the function prologue, in line with the PICO's executable code. This data must exist on a 4B boundary. This means, if you opt to extend this and stomp over an exported function, you'll want to take care to preserve the 4B alignment of your PICO's code.
Conversation
- Unveiling "Careto" - The Masked APT (2014) by authors at Kasperky documents an APT with an interesting tactic: "After the system library is loaded, its contents are overwritten with the malicious library, but the module path and other data are kept intact. So, to someone looking with a process analysis tool, the malicious library appears as a clean system DLL in the module list of the top process.". This is what inspired my interest in module stomping.
- In-memory Evasion (5 of 4) - Cobalt Strike 3.11 Addendum (2018) describes the module stomping added to Cobalt Strike 3.11
- Hiding malicious code with "Module Stomping": Part 1 (2019) by Aliz Hammond describes remote process module stomping
- Hiding malicious code with "Module Stomping": Part 3 (2019) by Aliz Hammond works through using copy-on-write of shared DLLs to find signs of module stomping
- DetectCobaltStomp (2020) by yusufqk acts on DONT_RESOLVE_DLL_REFERNCES as a tell to find Cobalt Strike's module stomping implementation. It'll work with this example too. I opted for DONT_RESOLVE_DLL_REFERENCES to make the Cobalt Strike feature less of an operator footgun.
- Analyzing Malware with Hooks, Stomps and Return-addresses (2022) by waldoirc walks through the above tell (briefly) and talks about more generic detection possibilities too
- [Brute Ratel] Release v1.5 (Nightmare) - Ghosts From The Past (2023) by Chetan Nayak introduces Advanced Module Stomping to address module stomping IOCs.
- Module Stomping (2023) by Dylan Tran surveys the advanced module stomping variants and implements some of the ideas as modifications to Kyle Avery's AceLdr.
- Astral Projection: Advanced Module Stomping (2026) by KuwaitiSt addresses some of the IOCs around finding signs of module modification in memory.
- Module Stomping PIC (2026) by Rasta Mouse shows how to module stomp PIC and PICOs with Crystal Palace and documents the process with a lot of detail and shows some alternative ways to similar ends (e.g., NtCreateSection/NtMapViewOfSection instead of LoadLibraryExW)
License
This project is licensed under the BSD License.