Skip to content

Memory Regions

Inside a Process

A process's memory is divided into regions, and each has a type and a protection. Code normally runs from image regions, which hold the program file and its DLLs. Private memory is the program's own working space, normally data that can be read and written but not run. A private region created to run and be written, with no file behind it, is a lead for code that arrived without the loader. Just-in-time compilers make such regions too, so check which program holds it.

What It Is

Every process gets its own private range of memory addresses, its address space. Windows divides it into regions, and marks each with what may be done there, such as read, write or run.

Why Windows Needs It
Keeping each program's memory private means one program cannot read or overwrite another's data by mistake. The marks stop a program running what should only be data, or changing its own code.
An Everyday Example
When Notepad starts, notepad.exe and its DLLs fill image regions that can run, and a font file it reads sits in a mapped region. The text alice types sits in its heap, private memory it can read and write but not run.
notepad.exe's address space, region by region (example values)

notepad.exe

  1. Imagenotepad.exe, the programRuns Code
  2. Imagekernel32.dll, user32.dll and its other DLLsRuns Code
  3. MappedA font file it readsRead Only
  4. PrivateIts heap, holding the text alice typesRead and Write
  5. PrivateA stack for each thread, its scratch padRead and Write

Only notepad.exe sees these addresses. Another program needs a handle with the right to read them.

Kept by the Kernel
The kernel keeps each region in the process's virtual address descriptor (VAD) tree, with the protection it was created with. Pages inside a region can take another protection later.

Every region carries a protection, which says whether it can be read, written or run. These are the four you will meet most, and where each one is normal.

Memory protections

ProtectionWhat It MeansNormal For
Execute, write copy (PAGE_EXECUTE_WRITECOPY)Code that can run, shared by every process that maps the same file. Windows copies a page for this process only if it writes there.Image regions, as created
Read and write (PAGE_READWRITE)Data that can change but not runHeaps and stacks
Execute and read (PAGE_EXECUTE_READ)Code that can run but not changeCode pages inside images, as a live tool shows them
Execute, read and write (PAGE_EXECUTE_READWRITE)Memory that can be written and runJust-in-time compilers, and a lead anywhere else

Three Kinds of Memory

Every region is image, mapped or private memory. Image regions hold code from files, mapped regions hold data files and shared memory, and private regions hold the heaps and stacks the program works in.

The picture marks each region with the protection it was created with. A live tool shows each part as it is now, so one region can appear as several rows with other protections.

The spooler on ws-042, region by region (story)
  • Image

    • spoolsv.exe and its DLLs, each from System32Protection When CreatedExecute, write copy
  • Mapped

    • Data files the spooler readsProtection When CreatedRead only
  • Private

    • Heaps and thread stacksProtection When CreatedRead and write
    • One region at 0x21C4F3A0000 that starts with MZ (4D 5A) and maps no fileProtection When CreatedExecute, read and write

What Normal Looks Like

On a healthy machine this part looks like this.

  • Code runs from image regions mapped from the executable and its DLLs, created as Execute, write copy.
  • Heaps and stacks are private memory that can be read and written but not run.
  • Programs with a just-in-time compiler, such as .NET programs and browsers, write code into private memory and run it, which is normal for them.

Why It Matters

Code that never came from a file has to live somewhere in memory. Private memory created to run and be written is where injected and reflectively loaded code usually sits, and no process list shows it.

Normal and Suspicious

A clean machine sits beside a suspicious one, and the pointer marks where to look.

Normal

A clean Windows 11 install

Two of spoolsv.exe's regions on a clean install, as windows.vadinfo lists them. Example values.
AddressTypeProtection When CreatedMapped File
0x7FF6B0000000Image (MEM_IMAGE)Execute, write copy (PAGE_EXECUTE_WRITECOPY)C:\Windows\System32\spoolsv.exe
0x1F5C2A10000Private (MEM_PRIVATE)Read and write (PAGE_READWRITE)None (no file)
See It in the Window

Suspicious

ws-042,

The spooler on ws-042 at 10:08 on 12 Oct 2026, in a memory image.
AddressTypeProtection When CreatedMapped File
0x7FF6B0000000Image (MEM_IMAGE)Execute, write copy (PAGE_EXECUTE_WRITECOPY)C:\Windows\System32\spoolsv.exe
0x21C4F3A0000Private (MEM_PRIVATE)Execute, read and write (PAGE_EXECUTE_READWRITE)None (no file)
Protection When CreatedCreated to run and be written, with no file behind it: code normally runs from image regions a file backs. Remote Thread Injection
See It in the Window

What a Malicious Example Shows

Each card is what malicious use of this part looks like, and where it shows.

  • A private region created to run and be written, starting with an MZ header or with code.Where it shows: windows.malware.malfind with Notes MZ header or Function prologue, or Windows.System.VAD filtered to executable memory with no file.
  • Executable memory holding a DLL that no loader list names and no file backs.Where it shows: A private region starting with an MZ header in windows.malware.ldrmodules, in no list.
  • An image region whose code in memory differs from its file on disk.Where it shows: Windows.Memory.Mem2Disk live. malfind never judges an image region created as Execute, write copy, so it can miss this.

Live and in Memory

Each question has the tools that answer it on a running machine, and in a memory image, a copy of its memory saved to a file.

In a memory image, windows.vadinfo lists each region with the protection it was created with, and windows.malware.malfind picks out executable regions that can be written or hold written pages. Live, Windows.System.VAD and VMMap show each run of pages with the protection it has now.

  • Which regions can run code, and is a file behind each?

    On a Running Machine

    In a Memory Image

  • Does code in an image region match its file on disk?

    On a Running Machine

    In a Memory Image

  • What does a suspect region hold?

    On a Running Machine

    In a Memory Image

To take it offline, read Dumping a Process and Memory

Reading Malfind Results

windows.malware.malfind lists private regions, and shared regions not created as Execute, write copy, that were created to run and be written, or that can run and hold written pages. Its Notes column reads MZ header, PE header or Function prologue when the first bytes match those patterns. That is a hint about what starts the region, not a verdict.

It judges the protection a region was created with, so a region created writable and made executable later shows a harmless creation protection, and a clean result proves nothing. It skips regions that are entirely paged out, moved from memory to the page file on disk, or zero.

Confirm a hit by reading the threads that start in the region, the handles other processes hold to this one, and the loader lists. Then dump the region, with the incident lead's agreement.

What It Misses

Every way of looking has gaps, so cover these from another source.

  • malfind judges the protection a region was created with, so a region made executable later looks harmless to it. It also skips any region that was entirely paged out or zero, so a clean result proves nothing. Live, Windows.System.VAD shows the protection each run of pages has now.
  • malfind never judges an image region created as Execute, write copy, so code written over a mapped image needs a check of memory against disk. Windows.Memory.Mem2Disk does that live, as Checking for Injected Code says.
  • Executable memory no file backs says nothing of who put the code there or when. Read which processes hold a handle to this one, and the remote thread records, Sysmon event 8 or Defender's DeviceEvents, where those run.

False Positives

These look odd but are normal, so rule them out before you act.

  • .NET, Java, browsers and other just-in-time compilers create private executable memory, so compare with a clean machine of the same build first.
  • Security products place their own code in the processes they watch, and packed programs unpack themselves in memory.

Red Flags It Explains

Each red flag below is confirmed by reading this part.

Checks That Use It

These checks read this part as one of their steps.

Hunt It

The same hunt is written for four tools, so pick the one you use. Defender XDR and Sentinel queries are in KQL, which you paste into Advanced hunting in the Defender portal or into Sentinel's Logs page. Splunk queries are in SPL, for its Search page, and Velociraptor queries are in VQL, which you run as a hunt.

Needs Defender for Endpoint. Microsoft's table page lists no action types, so confirm these with DeviceEvents | distinct ActionType, and expect them to be recorded selectively. Debuggers and security products touch other processes' memory too, so a rare pair is a lead to read in memory, not proof.

KQLDefender XDR, Advanced hunting
// Memory allocated, or its protection changed, by one process in another, rarest pairs firstDeviceEvents| where Timestamp > ago(30d)| where ActionType in ("NtAllocateVirtualMemoryRemoteApiCall", "MemoryRemoteProtect")| where ProcessId != InitiatingProcessId| summarize Devices = dcount(DeviceId), Events = count(), Actions = make_set(ActionType), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by InitiatingProcessFileName, InitiatingProcessFolderPath, FileName| order by Devices asc, Events asc

Sources

MITRE ATT&CK is a free public catalogue of the techniques attackers use. Each technique has an ID, such as T1055 for Process Injection, so defenders can name the same behaviour the same way. Reading this part helps find these techniques.