Sitemap
Reyadjr0x1

Reyadjr0x1

Windows Memory Forensics Series — Part 03: Process Creation Internals

11 min readSep 26, 2026

--

Parts 01 and 02 covered how to find processes and validate what’s loaded inside them. This part goes one level deeper: how a process actually comes into existence in the first place — from the double-click to the first executed instruction.

Understanding the creation flow in detail is what makes the forensic artifacts in Parts 01 and 02 make sense: why EPROCESS looks the way it does, why the PEB exists at all, and how the PE loading process, the VAD Tree, and memory paging all fit together.

1. What Happens When You Double-Click notepad.exe

Step 1: Request Execution (User Mode)

You double-click the file. The shell (e.g. explorer.exe) calls a function named CreateProcess.

Step 2: Create the EPROCESS (Kernel Mode)

The request drops into the kernel, which builds a data structure in its own memory called EPROCESS.

  • Purpose: this is the process’s official record — it holds the Process ID (PID), the security structure (Access Token), and which process is the parent.

Step 3: Allocate the Virtual Address Space

Windows builds a virtual address space for the process (e.g. 4GB on a 32-bit system, or a vastly larger space on 64-bit).

  • Purpose: give the process an empty address space, completely independent from every other process — without reserving any physical RAM yet.

Step 4: Read the PE Header and Map the Sections

Windows opens the .exe file on disk and reads its structure (the PE Header).

Step 5: Resolve Imports

Windows inspects the Imports section and loads the required DLLs (e.g. kernel32.dll), writing the real function addresses into a table called the IAT (Import Address Table).

Step 6: Create the Primary Thread and Start Execution

Windows creates an ETHREAD and sets up the CPU to begin executing code at the address written in AddressOfEntryPoint.

2. What Is EPROCESS, Exactly?

EPROCESS is a kernel data structure in Windows representing a process from the kernel’s point of view.

So when Windows creates a process such as:

notepad.exe
PID = 4200

the kernel holds an object/structure roughly called:

EPROCESS

representing that process and holding the information Windows needs to manage it.

2.1 EPROCESS — The Full Picture

EPROCESS
│
├── Object / Kernel Management
│ ├── Process Object Header
│ ├── Object information
│ └── Reference / handle-related information
│
├── Process Identity
│ ├── UniqueProcessId
│ ├── Image/File information
│ ├── Process flags
│ └── Process state
│
├── Process Relationships
│ ├── ActiveProcessLinks
│ ├── Parent Process
│ ├── Session information
│ └── Job information
│
├── Security
│ ├── Token
│ ├── Security context
│ └── Privilege-related information
│
├── Execution
│ ├── Threads
│ ├── Thread list
│ ├── Scheduling information
│ └── Process state
│
├── Memory Management
│ ├── Process Address Space
│ ├── Directory Table Base
│ ├── VAD information
│ ├── Working Set information
│ └── Memory-management structures
│
├── Handles / Objects
│ ├── Handle table
│ └── Object-related information
│
├── I/O
│ ├── I/O-related information
│ └── Device / file interaction state
│
├── Loader / Image Information
│ ├── Image file information
│ ├── Section information
│ └── Image-related metadata
│
└── Accounting / Statistics
├── CPU time
├── Memory usage
├── Quotas
└── Other accounting information

EPROCESS structures are not isolated from each other. Windows links them together in a linked list inside the kernel, so it can walk from one process to the next — this is the same list pslist (Part 01) traverses.

2.2 The Idea, Simplified

Imagine three processes:

explorer.exe   PID 1000
notepad.exe PID 2000
chrome.exe PID 3000

Windows can keep them connected like this:

EPROCESS              EPROCESS              EPROCESS
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ explorer │ │ notepad │ │ chrome │
│ PID 1000 │ │ PID 2000 │ │ PID 3000 │
│ │ │ │ │ │
│ ActiveLinks │──────►│ ActiveLinks │──────►│ ActiveLinks │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
└──────────────────────────────────────────┘

But in reality Windows uses a doubly linked list — every node has both:

Flink
Blink

2.3 Flink and Blink

EPROCESS A
│
├── Flink ──────► EPROCESS B
│
└── Blink ◄───── EPROCESS previous

So every process can find:

  • what comes after it, via Flink
  • what comes before it, via Blink
Flink
A ─────────────────► B
▲ │
│ │ Flink
│ ▼
└──────────────────── C
       Blink

2.4 Which Field Connects Them?

In modern Windows, EPROCESS contains a field called:

ActiveProcessLinks

of type:

LIST_ENTRY

and LIST_ENTRY itself is:

typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY;

So conceptually:

EPROCESS
│
├── UniqueProcessId
│
├── Token
│
├── ...
│
└── ActiveProcessLinks
├── Flink
└── Blink

ActiveProcessLinks is exactly what places an EPROCESS into the Active Process List.

2.5 Where Does the Kernel Start?

There is a head for the list, from which Windows begins its traversal:

PsActiveProcessHead
│
▼
EPROCESS A
│
Flink
▼
EPROCESS B
│
Flink
▼
EPROCESS C
│
Flink
▼
PsActiveProcessHead

In other words:

PsActiveProcessHead
↓
explorer
↓
notepad
↓
chrome
↓
...

This is fundamental to understanding how pslist works (see Part 01).

3. What Is the PE Header?

Press enter or click to view image in full size

Think of the PE Header as the program’s “ID card” or “specification sheet.” The moment you double-click an .exe, the OS reads this card to understand the file's dimensions, where to place it in RAM, and how to run it.

3.1 The DOS Header

The first data structure encountered at the very start of any Windows executable (.exe or .dll).

  • Fixed size: 64 bytes (0x40)
  • Located at offset 0x00
  • Contains many legacy fields (used by old MS-DOS systems), but modern Windows only cares about two of them:

1. The Magic Signature: e_magic

  • Location: the very start of the file, offset 0x00
  • Value: always 0x5A4D in hex, equal to the characters MZ (named after programmer Mark Zbikowski, who designed the format)
  • Purpose: Windows reads these two characters to confirm the file is actually a valid Windows executable; without MZ, the system refuses to run it

2. The Golden Pointer: e_lfanew

  • Location: at the end of the DOS Header, offset 0x3C
  • Purpose: holds a number (address/offset) pointing directly to the start of the real PE Header (the NT Headers) inside the file
  • Why it matters: without this pointer, Windows wouldn’t know exactly where the PE Header begins, since the space between the DOS Header and the PE Header can vary in size from file to file

3.2 The NT Headers (The Beating Heart)

The most important structure, containing 3 parts:

  • Signature — the PE-specific signature, the characters PE\0\0
  • File Header — basic information about the file itself:
  • Processor architecture (32-bit or 64-bit?)
  • Number of sections inside the file
  • File creation date/time
  • Optional Header — despite the name “optional,” it’s mandatory in .exe files:
  • AddressOfEntryPoint — the address where the processor begins executing code
  • ImageBase — the preferred address where the file wants to be loaded in memory
  • SizeOfImage — the total size the file occupies once unfolded in memory

3.3 The Section Table

Works like a conversion map that tells Windows how to take the data written in the file on disk and place it correctly in memory (RAM). Think of the Section Table as containing a “data form” for each section (like .text or .data), with 4 key parameters:

The 4 Key Parameters Per Section

Get Reyadjr0x1’s stories in your inbox

Join Medium for free to get updates from this writer.

Parameter Technical Name Simple Function Location on disk PointerToRawData Where the section starts inside the .exe file on disk Size on disk SizeOfRawData The real size of the section's data on disk Location in memory VirtualAddress (RVA) The address the section will land at in memory (relative to the program's base address) Size in memory VirtualSize The size the section will occupy in virtual memory

3.4 How Windows Maps a Section Like .text Into Memory

Let’s apply the formula to a practical example:

  1. Program base address (ImageBase): suppose Windows decides to load the program at address 0x400000 in memory
  2. Reading section data from the table: Windows looks at the Section Table row for .text and finds:
  • VirtualAddress = 0x1000
  • PointerToRawData = 0x400
  1. The mapping process:
  • Windows goes to the disk at location 0x400 and reads the instruction code
  • To calculate its final location in memory, it does a simple addition
  • As a result, Windows moves the code and places it at address 0x401000 in memory

3.5 Security Permissions (Characteristics)

The Section Table doesn’t just define addresses — it also gives each section specific access permissions:

  • .text section: gets Execute/Read permission (execute and read only), so the processor can execute the code, and no program can modify it
  • .data section: gets Read/Write permission, used to store variables

3.6 The Five Loading Stages

1. Headers Parsing

  • What happens: the OS opens the file and reads the main parts in order: DOS Header → PE Header → Optional Header
  • Goal: confirm the file is valid and intended for Windows, and learn the basic instructions for its size and location

2. Sections Table Parsing

  • What happens: the system reads the Section Table to verify its validity and boundaries
  • Goal: identify the sections present (like .text and .data) and how much space and what permissions each needs

3. Mapping

  • What happens: Windows builds the virtual address space and starts moving each section from disk into its appropriate address in memory, based on ImageBase and VirtualAddress
  • Goal: unfold the file’s parts inside RAM in an organized way

4. Imports Resolution

  • What happens: Windows looks at the Imports section (e.g. kernel32.dll or user32.dll), loads these libraries into memory, and writes the real function addresses into a table called the IAT (Import Address Table)
  • Goal: connect the program to the helper functions it needs from the system (e.g. a function to open a window or show a message)

5. Execution

  • What happens: the CPU jumps directly to the address written in AddressOfEntryPoint and executes the first instruction there
  • Result: the program starts running and its window appears

4. The PEB (Process Environment Block)

PEB stands for Process Environment Block — a data structure representing a process’s information in User Mode. Windows creates this structure for every running process so it can hold that process’s runtime information without constantly having to go back into Kernel Mode.

4.1 Key Elements of the PEB Structure

1. BeingDebugged

A one-byte field. Its value is 1 if the process is being traced by a debugger, and 0 if running normally. Attackers and malware check this field to apply Anti-Debugging techniques.

2. Ldr — PEB_LDR_DATA

A pointer to a structure containing a list of all modules and external DLLs loaded into the process. This list is a doubly linked list showing DLL addresses and their location in memory.

3. ProcessParameters — RTL_USER_PROCESS_PARAMETERS

A structure holding the process’s startup parameters, such as:

  • Executable file path
  • Command line
  • Current directory
  • Environment variables

4. ProcessHeap

A pointer to the process’s main heap, used for dynamic memory allocation.

5. ImageBaseAddress

A pointer to the address where the main .exe file is loaded within the process's virtual memory.

4.2 _EPROCESS Is Not a Direct "Container" of the PEB

The _EPROCESS object in the kernel does not contain the full PEB structure inside it — it only contains a pointer to the PEB's address in User Space:

  • In Kernel Space: the _EPROCESS structure contains a field called Peb, of type pointer (struct _PEB*)
  • In User Space: the actual memory where the PEB structure is built

6. The VAD Tree (Virtual Address Descriptor Tree) — In Depth

The VAD Tree is the fundamental data structure the kernel in Windows uses to track and count every memory region reserved inside a process’s Virtual Address Space.

Imagine the process’s Virtual Address Space is a huge piece of land. When the process wants to reserve a plot (carve out memory for Code, Stack, or Heap), the OS builds a land registry recording:

  • Where does this plot start and where does it end, address-wise?
  • What are this plot’s permissions? (Read-Only, Write, or Execute?)

That land registry, at the kernel level, is the VAD Tree.

6.1 Key Data Stored in Each Tree Node

Each node inside the VAD tree represents a reserved memory region and contains:

1. Addresses (Starting & Ending VPN)

Defines the start and end virtual memory address of the region reserved.

2. Allocation Type

Indicates whether the space is:

  • Private Memory: memory private to this process only (like the Heap and Stack)
  • Mapped File / Section: memory tied to a file on disk (like an .exe file or DLL files)

3. Protection Flags

Define what’s permitted on this region, such as:

  • PAGE_READONLY
  • PAGE_READWRITE
  • PAGE_EXECUTE_READWRITE (a very dangerous permission, because it allows writing and executing code in the same region at the same time)

7. What Is a Page, Simply Put?

Windows and the CPU don’t treat RAM as a random sea of bytes, and they don’t reserve memory byte-by-byte. Instead, they divide both virtual and physical memory into small, fixed-size blocks.

  • The standard size of a single Page on most systems is 4 Kilobytes (4096 bytes)
  • The Page is the smallest building-block unit the CPU and OS can reserve, move, or apply security permissions to (Read, Write, Execute)

7.1 Analogy: Being Inside the RAM Giant

Press enter or click to view image in full size

Imagine RAM as a giant notebook:

The Page (a page in the notebook): one sheet of the notebook (fixed size, 4KB)

  • You can’t tear off half a sheet and write on it — you either use the whole sheet or leave it empty

The PTE (Page Table Entry): the index tag glued to the top of that sheet

  • This tag says: “Where is this sheet actually located in real RAM? And is it allowed to be written to, or read-only?”

7.2 The Complete Architecture With the VAD Tree

To tie the whole picture together so it never gets confusing again:

  1. The VAD Node (tree node): represents a large space (e.g. a program requests 1 Megabyte). That space contains 256 pages
  2. The Pages: that 1 Megabyte gets split into 256 small chunks, each 4KB
  3. The PTE table (the tags): contains 256 entries (PTEs), each entry holding one page and responsible for translating its address and monitoring its current permissions in front of the CPU

8. Memory Management Mechanics

Imagine you want to reserve a table at a big restaurant:

8.1 Step One: Initial Reservation (MEM_RESERVE)

  • What happens? You call the restaurant and say: “I want to reserve a table for 10 people at 8.”
  • What does the restaurant do? It puts your name in the book: “Table 5 is reserved for so-and-so.”
  • In memory: Windows records in the VAD Tree that this address range (e.g. from 0x1000 to 0x5000) is reserved for your program.
  • The reality: no food is put on the table, and no space was actually pulled from real RAM — just “a name on paper.”

8.2 Step Two: Commitment (MEM_COMMITTED)

  • What happens? You confirm with the restaurant and say: “Prepare the order and the cost, we’re on our way.”
  • What does the restaurant do? It ensures it has enough food in the kitchen for 10 people, but hasn’t plated the food yet!
  • In memory: Windows checks RAM and the Page File and guarantees there’s enough free space for this page if you decide to use it, and sets the permissions (like Read/Write).
  • The reality: real RAM still hasn’t had anything placed into it!

8.3 Step Three: Actual Access (Page Fault, then Demand Paging)

  • What happens? The moment the guest sits down and reaches out to eat (i.e., the program tries to read or write to memory for the first time):
  • The CPU: checks the PTE table and finds the page empty, with no code actually backed by real RAM!
  • Reaction: the CPU raises an alarm called a Page Fault
  • The Kernel steps in: the kernel hears the alarm, goes and opens RAM, grabs a real free physical frame, links it to that address, and updates the PTE to make it valid (Valid = 1)
  • From this moment on: the data is actually inside RAM and you can use it directly!

Why This Matters for the Investigation

Everything explained in this part maps directly onto the forensic artifacts covered in Parts 01 and 02:

  • The EPROCESS/ActiveProcessLinks walk is exactly what pslist traverses, and exactly what DKOM manipulates
  • The PEB’s ImageBaseAddress field is exactly the value ldrmodules compares against the VAD
  • The VAD Tree’s Protection and Type fields are exactly what malfind and ldrmodules inspect to flag suspicious memory regions

--

--