HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": 395,
"key": "indirect-memory-writing",
"unprotect_id": "U0525",
"name": "Indirect Memory Writing",
"description": "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.\"\r\n\r\nIndirect 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.\r\n\r\nRather 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.\r\n\r\n### Example with WriteFile API\r\n\r\nWhen using the Windows API `WriteFile`, the call signature is \r\n\r\n```c\r\nBOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)\r\n```\r\n\r\nThe `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`. \r\n\r\n### AMSI Bypass\r\n\r\nFor 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.\r\n\r\n#### PowerShell Example\r\n\r\n```powershell\r\n# ... snip ...\r\n\r\n$payload = 0xcc, 0xcc, 0xcc, 0xcc, 0xcc ...\r\n\r\n$dummy = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(256)\r\ntry\r\n{\t\r\n\tfor ($i = 0; $i -lt $payload.Length; $i++)\r\n { \r\n $null = [W32]::ReadProcessMemory(\r\n -1,\r\n $dummy,\r\n $dummy,\r\n $payload[$i],\r\n [Int64]$payloadAddress + $i\r\n ) \r\n } \r\n}\r\nfinally\r\n{\r\n [System.Runtime.InteropServices.Marshal]::FreeHGlobal($dummy)\r\n}\r\n\r\n# ... snip ...\r\n```\r\n\r\n#### VBA Example\r\n\r\n```vb\r\n' ... snip ...\r\n\r\nDim XORKey As Variant \r\nXORKey = Array(... snip ...)\r\n\r\nDim Payload As Variant\r\n#If Win64 Then\r\n Payload = Array(... snip ...)\r\n#Else\r\n Payload = Array(... snip ...)\r\n#End If\r\n\r\nPayloadAddress = VirtualAlloc(0, UBound(Payload), &H3000, &H40)\r\n\r\nDim Dummy() As Byte\r\nReDim Dummy(255)\r\n\r\nDim PayloadByte As Long \r\nFor i = LBound(Payload) To UBound(Payload)\r\n PayloadByte = Payload(i) Xor XORKey(i Mod (UBound(XORKey) - LBound(XORKey) + 1))\r\n\r\n ReadProcessMemory -1, Dummy(0), Dummy(0), PayloadByte, PayloadAddress + i\r\nNext i\r\n\r\n' ... snip ...\r\n```\r\n\r\n### Detection\r\n\r\nBe 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.",
"windows": "",
"linux": "",
"macos": "",
"resources": "https://github.com/mimorep/Indirect-Shellcode-Executor\r\nhttps://github.com/chmod760/CopyReadProcessMemory",
"creation_date": "2025-09-29T12:32:49.827972Z",
"tags": "AMSI Bypass",
"modification_date": "2025-11-28T19:44:19.161009Z",
"category": [
2,
7
],
"rules": [],
"attachments": [],
"featured_api": [],
"contributors": [
4
]
}