Indirect Memory Writing
Created the Monday 29 September 2025. Updated 14 hours, 27 minutes ago.
In local memory movement scenarios, for example, when a loader places a payload into memory for execution, antimalware can detect malicious activity at the moment the payload bytes are written into the newly allocated executable memory region. Attackers may try to evade such detection by avoiding direct writes to new memory region and instead relying on other, legitimate Windows APIs that will cause the operating system to write data to a memory location the attacker controls. This high-level approach is referred to as "indirect memory writing."
Indirect memory writing leverages benign Windows APIs that accept pointer parameters used by the OS to return status or counts (for example, the number of bytes written). Because the caller supplies the pointer, an attacker who controls that pointer can cause the OS to write values into attacker-controlled memory when the API completes its operation. In effect, the API becomes a mechanism to transfer one or more bytes into a target buffer without performing an explicit memory copy from the attacker process into that buffer.
Rather than invoking a direct memory-write primitive, the attacker triggers a legitimate operation whose completion or status-reporting mechanism induces write to an address the attacker chose. From a defender's perspective, this is a form of behavioral evasion, the byte stores look like normal API usage rather than an obvious memory-copy of a payload.
Example with WriteFile API
When using the Windows API WriteFile, the call signature is
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
The nNumberOfBytesToWrite parameter is an unsigned 32‑bit count that tells the OS how many bytes from lpBuffer to send to the file and on successful completion the OS writes the total number of bytes actually written into the memory pointed to by lpNumberOfBytesWritten (a caller‑supplied LPDWORD). In other words, the API uses that pointer as an output slot for a 32‑bit completion value; if you supply nNumberOfBytesToWrite = 0x41 and the write succeeds, the value 0x41 will be stored at the address you passed as lpNumberOfBytesWritten.
AMSI Bypass
For example, when scripting local shellcode loaders in VBA or PowerShell, some antimalware engines, including Microsoft Defender, may flag the payload at the moment is copied into a newly allocated executable memory region. Relying on indirect memory writting techniquevia ReadProcessMemory or ReadFile depending on the strategy, can avoid existing signatures until they are updated.
PowerShell Example
# ... snip ...
$payload = 0xcc, 0xcc, 0xcc, 0xcc, 0xcc ...
$dummy = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(256)
try
{
for ($i = 0; $i -lt $payload.Length; $i++)
{
$null = [W32]::ReadProcessMemory(
-1,
$dummy,
$dummy,
$payload[$i],
[Int64]$payloadAddress + $i
)
}
}
finally
{
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($dummy)
}
# ... snip ...
VBA Example
' ... snip ...
Dim XORKey As Variant
XORKey = Array(... snip ...)
Dim Payload As Variant
#If Win64 Then
Payload = Array(... snip ...)
#Else
Payload = Array(... snip ...)
#End If
PayloadAddress = VirtualAlloc(0, UBound(Payload), &H3000, &H40)
Dim Dummy() As Byte
ReDim Dummy(255)
Dim PayloadByte As Long
For i = LBound(Payload) To UBound(Payload)
PayloadByte = Payload(i) Xor XORKey(i Mod (UBound(XORKey) - LBound(XORKey) + 1))
ReadProcessMemory -1, Dummy(0), Dummy(0), PayloadByte, PayloadAddress + i
Next i
' ... snip ...
Detection
Be aware that benign APIs can be repurposed to place data into attacker‑controlled addresses. When reversing a sample (Regardless of whether the file is a binary or a script), verify whether any API that accepts a caller‑provided output pointer is being used to write into memory regions that will later be executed or otherwise abused. Instrument both the API call and the destination address (pointer provenance), and inspect the write size and value semantics. These checks will help distinguish legitimate uses from stealthy payload assembly that avoids classic WriteProcessMemory/VirtualAlloc patterns.
Technique Identifier
Technique Tag
Code Snippets
Contributor
Additional Resources
External Links
The resources provided below are associated links that will give you even more detailed information and research on current evasion technique. It is important to note that, while these resources may be helpful, it is important to exercise caution when following external links. As always, be careful when clicking on links from unknown sources, as they may lead to malicious content.
- GitHub - mimorep/Indirect-Shellcode-Executor: Indirect-Shellcode-Executor expoits the miss-configuration/vulnerability present on the API Windows method ReadProcessMemory discovered by DarkCoderSc. It exploits the nature of the in/out pointer param named *lpNumberOfBytesRead, that enables to write into process memory without calling common API methods to do so such as memcpy, this is perfect
- GitHub - chmod760/CopyReadProcessMemory: Copia De un buffer Con ReadProcessMemory