migrate
command and process hollowing procedures from a 5+-year-old Carbanak malware available on GitHub, even with prior knowledge of what is going to be tested, and half a year to prepare if needed.kernel32!CreateRemoteThread
, but we are really talking about ntdll!NtCreateThreadEx
, or the kernel-mode target intercepted through kernel callbacks.msbuild.exe
creating a new thread in a remote process. Even though the criticality of a potential true positive would be quite high, after testing the rule author decided it is only suitable for low severity (probably due to FP-rate), which likely degrades the rule to an IR label/enrichment in most environments.FileProfile()
enrichment function - detects extremely rare files creating threads in remote processes. Very useful to implement in-house, but still unlikely to be found in EDRs in such a simple form, as it would cause substantial amounts of false positives in certain environments, and could prove difficult to maintain. starting process
≠ hosting process
- so monitoring only remote thread creation, usually also limited to those with:MEM_COMMIT
-type segmentX
target
) only in Windows built-in executablessource
) only in risky executables%userprofile%
, %temp%
etc.)ntdll!NtCreateThread(Ex)
hooking/thread creation callbacks nowadays is an easily exploitable design flaw.Windows Loader
or target application locally, and thus there is nothing to detect upon. This is one of the reasons CobaltStrike execute-assembly
uses SetThreadContext
instead of CRT injection on the sacrificial process.SetThreadContext
anomalies, than CRT-injection, and today in many environments it generates high criticality alerts, rendering fork&run useless in stealthy offensive ops.Asynchronous Procedure Calls
provide another avenue for avoiding thread creation. An APC can be queued for an existing thread, and executed once it enters an alertable state.ntdll!LdrpInitializeProcess
function had a chance to run. That way our scheduled routine is executed before the hooking DLLs are loaded into the target process.DripLoader is an evasive shellcode loader (injector) for bypassing event-based injection detection, without necessarily suppressing event collection.The project is aiming to highlight limitations of event-driven injection identification, and show the need for more advanced memory scanning and smarter local agent inventories in EDR.
DripLoader evades EDRs by
using the most risky APIs possible likeNtAllocateVirtualMemory
andNtCreateThreadEx
blending in with call arguments to create events that vendors are forced to drop or log&ignore due to volume avoiding multi-event correlation by introducing delays
PageSize
sized pages, which on Windows 10 with a modern processor is 4kB
:SYSTEM_INFO
structure tells us the lowest possible size of a VM allocation4kB
is by far the most prevalent allocation size (>95%), making it extremely challenging to detect onkernel32!VirtualAllocEx
choose the base, as it might reserve memory at an address where the other allocations will not fitkernel32!VirtualAllocEx
and similar is rounded up to AllocationGranularity
which is another constant found in SYSTEM_INFO
and is usually 64kB
4kB
of MEM_COMMIT | MEM_RESERVE
memory at 0x40000000
, the whole 0x40010000 (64kB)
region will be unavailable for new allocationsVirtualQueryEx
the target process to find the first region able to fit our shellcode blobAllocationGranularity (64kB)
sized regions, and then loop over those committing 4kB
pages to ensure page alignmentRegionSize
of a target memory page in properties of logged VirtualProtectEx
events. (TiEtw provides this, and hooks can too).CreateThreadEx
native API which is the ntdll target of CRT, and hence very commonly called by legitimate software. To bypass any detections we will:MEM_IMAGE
base addressWindows Loader
, ntdll.dll
far jmp
to our shellcode base at the time of thread creationMEM_IMAGE
segment, as we only care about logging arguments in the TiEtw/Hook event. beacon.dll),
the locally created thread won't be tagged on by most EDRs, but it will no longer have ntdll
as it's start address which could get it detected by basic Endpoint Protection, and will get it detected by Get-InjectedThread
.RVA
of the function we will hijackntdll
and calculate AVA
jmp
CreateRemoteThread